首页 > 编程语言 >【Spring AOP】【四】Spring AOP源码解析-AOP切入时机

【Spring AOP】【四】Spring AOP源码解析-AOP切入时机

时间:2023-02-20 08:11:36浏览次数:43  
标签:cacheKey Spring beanName 代理 Object bean 源码 AOP

1  前言

我们分析了AOP不管是XML配置还是注解方式的解析过程,这篇我们简单来说下AOP在Spring中对bean对象代理的一个切入时机,其实我们在讲解IOC的时候,已经点了一下这篇我们再来简单说一下。

2  源码分析

我们知道AOP有个核心类大哥AbstractAutoProxyCreator, 他实现了BeanPostProcessor的postProcessAfterInitialization方法,其实就是在这里进行bean的AOP织入的,我们来看下源码:

public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
        implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
        
    @Override
    // bean 初始化后置处理方法
    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
        if (bean != null) {
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            if (this.earlyProxyReferences.remove(cacheKey) != bean) {
                // 如果需要,为 bean 生成代理对象
                return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        return bean;
    }
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
        return bean;
    }
    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
        return bean;
    }
    /*
      如果是基础设施类(Pointcut、Advice、Advisor 等接口的实现类),或是应该跳过的类,
      则不应该生成代理,此时直接返回 bean
      也就是代理不能给自己再加代理 就是不套娃
     */
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
        // 将 <cacheKey, FALSE> 键值对放入缓存中 缓存你懂的
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }
    // 为目标 bean 查找合适的通知器
    // Create proxy if we have advice.
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    /*
      若 specificInterceptors != null,即 specificInterceptors != DO_NOT_PROXY,
      则为 bean 生成代理对象,否则直接返回 bean
     */
    if (specificInterceptors != DO_NOT_PROXY) {
        this.advisedBeans.put(cacheKey, Boolean.TRUE);
        // 创建代理
        Object proxy = createProxy(
                bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
        this.proxyTypes.put(cacheKey, proxy.getClass());
        /*
          返回代理对象,此时 IOC 容器输入 bean,得到 proxy。此时,
          beanName 对应的 bean 是代理对象,而非原始的 bean
         */
        return proxy;
    }
    
    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
}

以上就是 Spring AOP 创建代理对象的入口方法分析,过程比较简单,这里简单总结一下:

  1. 若 bean 是 AOP 基础设施类型,则直接返回
  2. 为 bean 查找合适的通知器
  3. 如果通知器数组不为空,说明bean需要代理,则为 bean 生成代理对象,并返回代理对象
  4. 若数组为空,则返回原始 bean即自己

3  小结

本篇我们简单了解下AOP的织入时机,接下来我们就看看AOP是如何筛选通知器的,并如何串联编排多个通知器的,休息一下,我们再继续。

标签:cacheKey,Spring,beanName,代理,Object,bean,源码,AOP
From: https://www.cnblogs.com/kukuxjx/p/17136107.html

相关文章

  • 【Spring AOP】【五】Spring AOP源码解析-筛选编排合适的通知器
    1 前言我们了解过AOP配置解析以及AOP的切入时机,那么这篇我们看看,AOP是如何给某个Bean筛选合适的通知器。2 源码分析2.1 方法通读我们从AOP切入时机中,为当前bean......
  • 【Spring AOP】【三】Spring AOP源码解析-注解方式加载解析过程
    1 前言上一篇我们讲解了XML方式解析AOP的配置,这篇我们来解析下注解方式的解析过程。2 代码准备@Component@AspectpublicclassMyAspect{@Pointcut("exec......
  • spring,自定义注解,工厂模式,策略模式优化 if else,jdk1.7
    最近项目中使用mqtt监听消息,再根据消息做各种处理,使用大量的ifelse,代码异常难维护,参考的地址找不到了。。。 以下为实现:接收mqtt的接口类packagecom.mhm.mqttlistener;im......
  • Springcloud环境中bootstrap.yml加载原理
    如果是Springcloud项目,一般会将配置中心、注册中心等地址存入bootstrap.yml中,同时将其他的配置存入配置中心。也就是说bootstrap.yml的读取会比较靠前。下面研究其机......
  • 【Spring AOP】【一】Spring AOP源码解析文章导读
    1 前言IOC的一些东西我们说过了,这篇我们开始看看AOP,面向切面编程,他也是Spring的一个核心功能,他的作用就是给我们的Bean创建代理对象,进行功能增强,比如我们的事务、日志等......
  • SpringBoot文件上传
    文件上传引入依赖<!--文件上传--><dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifact......
  • 【Spring AOP】【二】Spring AOP源码解析-XML方式加载解析过程
    1 前言这篇我们看一下,我们的AOP代码是怎么被Spring加载的进去的,那么分两种一种是XML配置的,一种就是我们常用的注解,我们从源码先看下XML方式的都是怎么被加载解析的。2......
  • Spring-IOC、AOP、事务的说明
    今天来聊一聊我对spring框架的认识,本篇章中不详细讲解具体的使用方法和实现一、spring是什么?spring是一个java语言下的bean管理的基础框架。二、spring的常用功能有那......
  • SpringBoot升级到3.0
    SpringBoot3.0出来有一段时间了,一直没时间来整理,这次来看一下吧。SpringBoot可以轻松创建独立的、生产级的基于Spring的应用程序,您可以“直接运行”。1.SpringBoo......
  • springboot mybatis (关联关系:一对一,一对多,多对多)
    例如这个学生选课的这个:这个里面课程跟老师是1对1的,而老师对课程是1对多的,一个课程只能由一个老师教,而一个老师可以教多个课程对于学生和课程之间是多对多的,一个学生可以......