目录

spring注解驱动之自动AOP

AOP:指在程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式;主要用到动态代理的技术

功能演示

演示步骤

  1. 导入aop模块;Spring AOP:(spring-aspects),aspectjweaver

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aspects</artifactId>
                <version>5.2.9.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjweaver</artifactId>
                <version>1.9.6</version>
            </dependency>
    
  2. 定义一个业务逻辑类(MathCalculator);在业务逻辑运行的时候将日志进行打印(方法之前、方法运行结束、方法返回,方法出现异常,xxx)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    package com.eh.aop;
       
    public class MathCalculator {
       
        public int div(int i, int j) {
            System.out.println("MathCalculator...div...");
            return i / j;
        }
    }
    
  3. 定义一个日志切面类(LogAspects):切面类里面的方法需要动态感知MathCalculator.div运行到哪里然后执行;

    通知方法:

    •      前置通知(@Before):logStart:在目标方法(div)运行之前运行
      
    •      后置通知(@After):logEnd:在目标方法(div)运行结束之后运行(无论方法正常结束还是异常结束)
      
    •      返回通知(@AfterReturning):logReturn:在目标方法(div)正常返回之后运行
      
    •      异常通知(@AfterThrowing):logException:在目标方法(div)出现异常以后运行
      
    •      环绕通知(@Around):动态代理,手动推进目标方法运行(joinPoint.procced())
      
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    
    package com.eh.aop;
       
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.*;
       
    import java.util.Arrays;
       
    /**
     * 切面类
     *
     * @Aspect: 告诉Spring当前类是一个切面类
     */
    @Aspect
    public class LogAspects {
       
        //抽取公共的切入点表达式
        //1、本类引用 pointCut()
        //2、其他的切面引用 com.eh.aop.LogAspects.pointCut()
        @Pointcut("execution(public int com.eh.aop.MathCalculator.*(..))")
        public void pointCut() {
        }
       
        //@Before在目标方法之前切入;切入点表达式(指定在哪个方法切入)
        @Before("pointCut()")
        public void logStart(JoinPoint joinPoint) {
            Object[] args = joinPoint.getArgs();
            System.out.println("" + joinPoint.getSignature().getName() + "运行。。。@Before:参数列表是:{" + Arrays.asList(args) + "}");
        }
       
        @After("com.eh.aop.LogAspects.pointCut()")
        public void logEnd(JoinPoint joinPoint) {
            System.out.println("" + joinPoint.getSignature().getName() + "结束。。。@After");
        }
       
        //如果要注入JoinPoint,JoinPoint一定要出现在参数表的第一位
        @AfterReturning(value = "pointCut()", returning = "result")
        public void logReturn(JoinPoint joinPoint, Object result) {
            System.out.println("" + joinPoint.getSignature().getName() + "正常返回。。。@AfterReturning:运行结果:{" + result + "}");
        }
       
        @AfterThrowing(value = "pointCut()", throwing = "exception")
        public void logException(JoinPoint joinPoint, Exception exception) {
            System.out.println("" + joinPoint.getSignature().getName() + "异常。。。异常信息:{" + exception + "}");
        }
    }
    
  4. 给切面类的目标方法标注何时何地运行(通知注解);

  5. 将切面类和业务逻辑类(目标方法所在类)都加入到容器中;

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    
    @EnableAspectJAutoProxy
    @Configuration
    public class MainConfig {
        //业务逻辑类加入容器中
        @Bean
        public MathCalculator calculator() {
            return new MathCalculator();
        }
       
        //切面类加入到容器中
        @Bean
        public LogAspects logAspects() {
            return new LogAspects();
        }
    }
    
  6. 必须告诉Spring哪个类是切面类(给切面类上加一个注解:@Aspect)

  7. 给配置类中加 @EnableAspectJAutoProxy 【开启基于注解的aop模式】

    相当于之前在配置文件中写<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

  8. 测试

    1
    2
    3
    
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
    MathCalculator calculator = applicationContext.getBean("calculator", MathCalculator.class);
    calculator.div(10, 2);
    
  9. 运行结果:

    1
    2
    3
    4
    
    div运行。。。@Before:参数列表是{[10, 2]}
    MathCalculator...div...
    div正常返回。。。@AfterReturning:运行结果{5}
    div结束。。。@After
    

    异常:

    1
    2
    3
    4
    
    div运行。。。@Before:参数列表是:{[10, 0]}
    MathCalculator...div...
    div异常。。。异常信息:{java.lang.ArithmeticException: / by zero}
    div结束。。。@After
    

小结

  1. 将业务逻辑组件和切面类都加入到容器中;告诉Spring哪个是切面类(@Aspect)
  2. 在切面类上的每一个通知方法上标注通知注解,告诉Spring何时何地运行(切入点表达式)
  3. 开启基于注解的aop模式;@EnableAspectJAutoProxy

AOP原理

分析aop的原理从3个方面着手:

  1. 看给容器中注册了什么组件

    AnnotationAwareAspectJAutoProxyCreator

  2. 这个组件什么时候工作

    每一个bean创建之前,调用它的postProcessBeforeInstantiation();

  3. 这个组件的功能是什么

关键组件

  1. @EnableAspectJAutoProxy

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Import(AspectJAutoProxyRegistrar.class)
    public @interface EnableAspectJAutoProxy { 
       
       /**
        * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
        * to standard Java interface-based proxies. The default is {@code false}.
        */
       boolean proxyTargetClass() default false;
       
       /**
        * Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal}
        * for retrieval via the {@link org.springframework.aop.framework.AopContext} class.
        * Off by default, i.e. no guarantees that {@code AopContext} access will work.
        * @since 4.3.1
        */
       boolean exposeProxy() default false;
       
    }
    
  2. 由注解定义得知给容器中导入了AspectJAutoProxyRegistrar

    AspectJAutoProxyRegistrar实现了ImportBeanDefinitionRegistrar

    1
    2
    
    利用AspectJAutoProxyRegistrar自定义给容器中注册bean
    AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
    

    最终注册了一个id是org.springframework.aop.config.internalAutoProxyCreator的将注册AnnotationAwareAspectJAutoProxyCreator的BeanDefinition, AnnotationAwareAspectJAutoProxyCreator->注解装配AspectJ自动代理创建器

  3. 分析AnnotationAwareAspectJAutoProxyCreator

    http://img.cana.space/picStore/20201029151701.png

    可以看到AnnotationAwareAspectJAutoProxyCreator实现了两个重要的接口

    • SmartInstantiationAwareBeanPostProcessor(后置处理器)
    • BeanFactoryAware,自动装配BeanFactory
  4. 后置处理器逻辑和装配BeanFactory逻辑实现的地方

    自动装配BeanFactory逻辑

    org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#setBeanFactory

    setBeanFactory中有用到initBeanFactory方法由子类实现

    org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator#initBeanFactory

    后置处理器逻辑

    org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessBeforeInstantiation

    org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization

  5. 我们给这4个关键地方加上被切面类和切面类注册的地方打上断点,进行debug调试来分析流程

什么时候工作

流程分析

创建和注册AnnotationAwareAspectJAutoProxyCreator的过程

  1. 传入配置类,创建ioc容器

  2. 注册配置类,调用refresh()刷新容器;

  3. registerBeanPostProcessors(beanFactory);

    注册bean的后置处理器来拦截bean的创建;

    org.springframework.context.support.PostProcessorRegistrationDelegate#registerBeanPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, org.springframework.context.support.AbstractApplicationContext)

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    
    public static void registerBeanPostProcessors(
          ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
       
      // 1. 先获取ioc容器已经定义了的需要创建对象的所有BeanPostProcessor
       String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
       
       int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
      // 2. 给容器中加别的BeanPostProcessor,主要用来做一些check
       beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
       
       // 将 BeanPostProcessors 分成3块,1. implement PriorityOrdered, 2. Ordered, 3.the rest.
       
       List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
       List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
       
       List<String> orderedPostProcessorNames = new ArrayList<>();
       
       List<String> nonOrderedPostProcessorNames = new ArrayList<>();
       for (String ppName : postProcessorNames) {
          if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
             BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
             priorityOrderedPostProcessors.add(pp);
             if (pp instanceof MergedBeanDefinitionPostProcessor) {
                internalPostProcessors.add(pp);
             }
          }
          else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
             orderedPostProcessorNames.add(ppName);
          }
          else {
             nonOrderedPostProcessorNames.add(ppName);
          }
       }
       
      // 3. 优先注册实现了PriorityOrdered接口的BeanPostProcessor;
       sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
       registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
       
      // 4. 再给容器中注册实现了Ordered接口的BeanPostProcessor;
     // AnnotationAwareAspectJAutoProxyCreator实现了Order,所以被添加在orderedPostProcessorNames
       List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
       for (String ppName : orderedPostProcessorNames) {
         // 这个方法里面创建id是x.xxx.xxx.internalAutoProxyCreator的BeanPostProcessor【类型是AnnotationAwareAspectJAutoProxyCreator】
          BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
          orderedPostProcessors.add(pp);
          if (pp instanceof MergedBeanDefinitionPostProcessor) {
             internalPostProcessors.add(pp);
          }
       }
      // 排序
       sortPostProcessors(orderedPostProcessors, beanFactory);
    // 注册BeanPostProcessor,实际上就是将刚创建BeanPostProcessor对象,保存在beanFactory中,也就是后面要提到的DefaultSingletonBeanRegistry,
       registerBeanPostProcessors(beanFactory, orderedPostProcessors);
       
      // 5. 注册没实现优先级接口的BeanPostProcessor;
       List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
       for (String ppName : nonOrderedPostProcessorNames) {
          BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
          nonOrderedPostProcessors.add(pp);
          if (pp instanceof MergedBeanDefinitionPostProcessor) {
             internalPostProcessors.add(pp);
          }
       }
       registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
       
       // Finally, re-register all internal BeanPostProcessors.
       sortPostProcessors(internalPostProcessors, beanFactory);
       registerBeanPostProcessors(beanFactory, internalPostProcessors);
       
       // Re-register post-processor for detecting inner beans as ApplicationListeners,
       // moving it to the end of the processor chain (for picking up proxies etc).
       beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
    }
    

    我们看看AnnotationAwareAspectJAutoProxyCreator是如何被创建的,进入到下面这个方法:

    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean

      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    
    protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
          throws BeanCreationException {
       
       // 1. 创建Bean的实例
       BeanWrapper instanceWrapper = null;
      // 解决循环依赖,如果是单例,将beanName从factoryBeanInstanceCache中移除
       if (mbd.isSingleton()) {
          instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
       }
      // 创建Bean id=org.springframework.aop.config.internalAutoProxyCreator,mbd是RootBeanDefinition,里面有设置类型是AnnotationAwareAspectJAutoProxyCreator
       if (instanceWrapper == null) {
         // 创建AnnotationAwareAspectJAutoProxyCreator的逻辑
          instanceWrapper = createBeanInstance(beanName, mbd, args);
       }
       Object bean = instanceWrapper.getWrappedInstance();
       Class<?> beanType = instanceWrapper.getWrappedClass();
       if (beanType != NullBean.class) {
          mbd.resolvedTargetType = beanType;
       }
       
       // Allow post-processors to modify the merged bean definition.
       synchronized (mbd.postProcessingLock) {
          if (!mbd.postProcessed) {
             try {
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
             }
             catch (Throwable ex) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                      "Post-processing of merged bean definition failed", ex);
             }
             mbd.postProcessed = true;
          }
       }
       
      // 处理循环依赖
       // Eagerly cache singletons to be able to resolve circular references
       // even when triggered by lifecycle interfaces like BeanFactoryAware.
       boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
             isSingletonCurrentlyInCreation(beanName));
       if (earlySingletonExposure) {
          if (logger.isTraceEnabled()) {
             logger.trace("Eagerly caching bean '" + beanName +
                   "' to allow for resolving potential circular references");
          }
          addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
       }
       
       // Initialize the bean instance.
       Object exposedObject = bean;
       try {
         // 2. populateBean;给bean的各种属性赋值
          populateBean(beanName, mbd, instanceWrapper);
         // 3. 初始化bean
          exposedObject = initializeBean(beanName, exposedObject, mbd);
       }
       catch (Throwable ex) {
          if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
             throw (BeanCreationException) ex;
          }
          else {
             throw new BeanCreationException(
                   mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
          }
       }
       
       if (earlySingletonExposure) {
          Object earlySingletonReference = getSingleton(beanName, false);
          if (earlySingletonReference != null) {
             if (exposedObject == bean) {
                exposedObject = earlySingletonReference;
             }
             else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                String[] dependentBeans = getDependentBeans(beanName);
                Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
                for (String dependentBean : dependentBeans) {
                   if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                      actualDependentBeans.add(dependentBean);
                   }
                }
                if (!actualDependentBeans.isEmpty()) {
                   throw new BeanCurrentlyInCreationException(beanName,
                         "Bean with name '" + beanName + "' has been injected into other beans [" +
                         StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                         "] in its raw version as part of a circular reference, but has eventually been " +
                         "wrapped. This means that said other beans do not use the final version of the " +
                         "bean. This is often the result of over-eager type matching - consider using " +
                         "'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
                }
             }
          }
       }
       
       // Register bean as disposable.
       try {
          registerDisposableBeanIfNecessary(beanName, bean, mbd);
       }
       catch (BeanDefinitionValidationException ex) {
          throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
       }
       
       return exposedObject;
    }
    

    创建Bean逻辑

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    
    protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
         try {
             Object beanInstance;
             if (System.getSecurityManager() != null) {
                 beanInstance = AccessController.doPrivileged(
                         (PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(mbd, beanName, this),
                         getAccessControlContext());
             }
             else {
            // 使用CglibSubclassingInstantiationStrategy初始化AnnotationAwareAspectJAutoProxyCreator
            // 这个里面是调用BeanUtils.instantiateClass(constructorToUse) 创建一个wrapper对象
                 beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
             }
             BeanWrapper bw = new BeanWrapperImpl(beanInstance);
             initBeanWrapper(bw);
             return bw;
         }
         catch (Throwable ex) {
             throw new BeanCreationException(
                     mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
         }
     }
    

    初始Bean逻辑

    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    
    protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
       if (System.getSecurityManager() != null) {
          AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            // 1. invokeAwareMethods():处理Aware接口的方法回调
            // 这里将工厂 AbstractAutowireCapableBeanFactory注册到了id是org.springframework.aop.config.internalAutoProxyCreator的Bean
             invokeAwareMethods(beanName, bean);
             return null;
          }, getAccessControlContext());
       }
       else {
          invokeAwareMethods(beanName, bean);
       }
       
       Object wrappedBean = bean;
       if (mbd == null || !mbd.isSynthetic()) {
         // 应用后置处理器的postProcessBeforeInitialization()
          wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
       }
       
       try {
         // 执行自定义的初始化方法
          invokeInitMethods(beanName, wrappedBean, mbd);
       }
       catch (Throwable ex) {
          throw new BeanCreationException(
                (mbd != null ? mbd.getResourceDescription() : null),
                beanName, "Invocation of init method failed", ex);
       }
       if (mbd == null || !mbd.isSynthetic()) {
         // 执行后置处理器的postProcessAfterInitialization
          wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
       }
       
       return wrappedBean;
    }
    

    至此,BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)创建成功;并且将原先的工厂ConfigurableListableBeanFactory包装成了BeanFactoryAspectJAdvisorsBuilder

    注册AnnotationAwareAspectJAutoProxyCreator

    org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#addSingleton

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    
    protected void addSingleton(String beanName, Object singletonObject) {
       synchronized (this.singletonObjects) {
         // 将新创建的bean AnnotationAwareAspectJAutoProxyCreator放到一级缓存中
          this.singletonObjects.put(beanName, singletonObject);
         // 从三级缓存移除
          this.singletonFactories.remove(beanName);
         // 从二级缓存移除
          this.earlySingletonObjects.remove(beanName);
         // 将beanName放入LinkedHashSet中,用来提升性能
          this.registeredSingletons.add(beanName);
       }
    }
    

    这里简单捋一下DefaultSingletonBeanRegistry和ConfigurableListableBeanFactory的关系,ConfigurableListableBeanFactory将要被包装成BeanFactoryAspectJAdvisorsBuilder,整理成下图:

    http://img.cana.space/picStore/20201029173013.png

    可以看到BeanFactoryAspectJAdvisorsBuilder包含了工厂,工厂即容器,包含了BeanProcessor(AnnotationAwareAspectJAutoProxyCreator)。

    注意
    注册BeanPostProcessor,实际上就是将刚创建BeanPostProcessor对象,保存在beanFactory中

创建完AnnotationAwareAspectJAutoProxyCreator后,AnnotationAwareAspectJAutoProxyCreator这个BeanProcessor是如何调用后置处理逻辑postProcessBeforeInstantiation方法的

关键组件 一节提到AnnotationAwareAspectJAutoProxyCreator的父类AbstractAutoProxyCreator

1
2
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
      implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {

实现了SmartInstantiationAwareBeanPostProcessor接口,接口继承关系如下

SmartInstantiationAwareBeanPostProcessor -> InstantiationAwareBeanPostProcessor -> BeanPostProcessor

在这一节也分析出了后置处理只有在实现InstantiationAwareBeanPostProcessor的两个方法中有增加具体的逻辑,

org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation

org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation

实现BeanPostProcessor的两个方法并没有增加具体逻辑

org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization

org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization

那么接下来我们分析在创建完AnnotationAwareAspectJAutoProxyCreator后,AnnotationAwareAspectJAutoProxyCreator这个BeanPostProcessor是如何调用后置处理逻辑postProcessBeforeInstantiation方法的

继续上一节Debug,将断点打在org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation

  1. finishBeanFactoryInitialization(beanFactory);完成BeanFactory初始化工作;创建剩下的单实例bean

  2. 遍历获取容器中所有的Bean,依次创建对象getBean(beanName),注意后续对切面类bean和被切面类bean的处理逻辑

    http://img.cana.space/picStore/20201029183700.png

  3. org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>)

    先从缓存中获取当前bean,如果能获取到,说明bean是之前被创建过的,直接使用,否则再创建;只要创建好的Bean都会被缓存起来

  4. org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])

    真正去创建一个Bean,下面的代码不完整,去除了一些逻辑方便阅读

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    
    protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
          throws BeanCreationException {
       
       RootBeanDefinition mbdToUse = mbd;
       
       Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
       if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
          mbdToUse = new RootBeanDefinition(mbd);
          mbdToUse.setBeanClass(resolvedClass);
       }
       
       
       try {
         // 给BeanPostProcessors一个返回代理目标对象的机会
          // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
          Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
          if (bean != null) {
            // 只要获取到了代理对象就直接返回
             return bean;
          }
       }
       catch (Throwable ex) {
          throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                "BeanPostProcessor before instantiation of bean failed", ex);
       }
       
       try {
         // 真正去创建目标对象,逻辑与之前创建BeanProcessor一样
          Object beanInstance = doCreateBean(beanName, mbdToUse, args);
          if (logger.isTraceEnabled()) {
             logger.trace("Finished creating instance of bean '" + beanName + "'");
          }
          return beanInstance;
       }
       catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
          // A previously detected exception with proper bean creation context already,
          // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
          throw ex;
       }
       catch (Throwable ex) {
          throw new BeanCreationException(
                mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
       }
    }
    
  5. org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInstantiation

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    
    protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
      // 拿到所有后置处理器,如果是InstantiationAwareBeanPostProcessor;就执行postProcessBeforeInstantiation
       for (BeanPostProcessor bp : getBeanPostProcessors()) {
          if (bp instanceof InstantiationAwareBeanPostProcessor) {
            // 我们的AnnotationAwareAspectJAutoProxyCreator就是一个InstantiationAwareBeanPostProcessor,所以会进来执行AnnotationAwareAspectJAutoProxyCreator的postProcessBeforeInstantiation方法, 该方法逻辑在父类AbstractAutoProxyCreator中实现
             InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
             Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
             if (result != null) {
                return result;
             }
          }
       }
       return null;
    }
    
  6. 至此,程序来到org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessBeforeInstantiation

AnnotationAwareAspectJAutoProxyCreator的作用

从前面我们得知每一个bean创建之前,都会调用postProcessBeforeInstantiation();

接下来着重看MathCalculator和LogAspect的创建

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessBeforeInstantiation

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
   Object cacheKey = getCacheKey(beanClass, beanName);

  // advisedBeans
   if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
      if (this.advisedBeans.containsKey(cacheKey)) {
         return null;
      }
     // 判断当前bean是否是基础类型的Advice、Pointcut、Advisor、AopInfrastructureBean,或者是否是切面(@Aspect)
     // 是否需要跳过
      if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
         this.advisedBeans.put(cacheKey, Boolean.FALSE);
         return null;
      }
   }

   TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
   if (targetSource != null) {
      if (StringUtils.hasLength(beanName)) {
         this.targetSourcedBeans.add(beanName);
      }
      Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
      Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
      this.proxyTypes.put(cacheKey, proxy.getClass());
      return proxy;
   }

   return null;
}

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization

创建代理对象

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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;
   }
   if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
      this.advisedBeans.put(cacheKey, Boolean.FALSE);
      return bean;
   }

   // Create proxy if we have advice.
  // 获取当前bean的所有增强器(通知方法) 
  /* 1、找到候选的所有的增强器(找哪些通知方法是需要切入当前bean方法的)
		2、获取到能在bean使用的增强器。
 		3、给增强器排序
   */
   Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
   if (specificInterceptors != DO_NOT_PROXY) {
     // 保存当前bean在advisedBeans中;
      this.advisedBeans.put(cacheKey, Boolean.TRUE);
     // 如果当前bean需要增强,创建当前bean的代理对象;
     /*
     1)、获取所有增强器(通知方法)
 * 			2)、保存到proxyFactory
 * 			3)、创建代理对象:Spring自动决定
 * 				JdkDynamicAopProxy(config);jdk动态代理;
 * 				ObjenesisCglibAopProxy(config);cglib的动态代理;
     */
     // 给容器中返回当前组件使用cglib增强了的代理对象;
      Object proxy = createProxy(
            bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
     // 放到缓存中
      this.proxyTypes.put(cacheKey, proxy.getClass());
      return proxy;
   }

   this.advisedBeans.put(cacheKey, Boolean.FALSE);
   return bean;
}

选择使用jdk动态代理还是使用cglib

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
   if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
      Class<?> targetClass = config.getTargetClass();
      if (targetClass == null) {
         throw new AopConfigException("TargetSource cannot determine target class: " +
               "Either an interface or a target is required for proxy creation.");
      }
      if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
         return new JdkDynamicAopProxy(config);
      }
      return new ObjenesisCglibAopProxy(config);
   }
   else {
      return new JdkDynamicAopProxy(config);
   }
}

以后容器中获取到的就是这个组件的代理对象,执行目标方法的时候,代理对象就会执行通知方法的流程;

注意:从spring3.2以后,spring框架本身不在需要cglib这个jar包了,因为cjlib.jar已经被spring项目的jar包集成进去。

为了防止项目中其他对cglib版本依赖不一样的冲突。

目标方法执行

获取拦截器链

容器中保存了组件的代理对象(cglib增强后的对象),这个对象里面保存了详细信息(比如增强器,目标对象,xxx);

org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor#intercept

拦截目标方法的执行

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
   Object oldProxy = null;
   boolean setProxyContext = false;
   Object target = null;
   TargetSource targetSource = this.advised.getTargetSource();
   try {
      if (this.advised.exposeProxy) {
         // Make invocation available if necessary.
         oldProxy = AopContext.setCurrentProxy(proxy);
         setProxyContext = true;
      }
      // Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
      target = targetSource.getTarget();
      Class<?> targetClass = (target != null ? target.getClass() : null);
     // 根据ProxyFactory对象获取将要执行的目标方法拦截器链;
     /*
     1. List<Object> interceptorList保存所有拦截器 5
 * 				一个默认的ExposeInvocationInterceptor 和 4个增强器;
 2. 遍历所有的增强器,将其转为Interceptor;
 * 				registry.getInterceptors(advisor);
 3. 将增强器转为List<MethodInterceptor>;
 * 				如果是MethodInterceptor,直接加入到集合中
 * 				如果不是,使用AdvisorAdapter将增强器转为MethodInterceptor;
 * 				转换完成返回MethodInterceptor数组;
     */
      List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
      Object retVal;
      /*
      如果没有拦截器链,直接执行目标方法;
 * 			拦截器链(每一个通知方法又被包装为方法拦截器,利用MethodInterceptor机制)
      */
      if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
         // We can skip creating a MethodInvocation: just invoke the target directly.
         // Note that the final invoker must be an InvokerInterceptor, so we know
         // it does nothing but a reflective operation on the target, and no hot
         // swapping or fancy proxying.
         Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
         retVal = methodProxy.invoke(target, argsToUse);
      }
      else {
         // We need to create a method invocation...
        /*
        如果有拦截器链,把需要执行的目标对象,目标方法,
 * 			拦截器链等信息传入创建一个 CglibMethodInvocation 对象,
 * 			并调用 Object retVal =  mi.proceed();
        */
         retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
      }
      retVal = processReturnType(proxy, target, method, retVal);
      return retVal;
   }
   finally {
      if (target != null && !targetSource.isStatic()) {
         targetSource.releaseTarget(target);
      }
      if (setProxyContext) {
         // Restore old proxy.
         AopContext.setCurrentProxy(oldProxy);
      }
   }
}

拦截器链的触发过程;

20201029210430

创建CglibMethodInvocation对象

1
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();

proceed()执行过程

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public Object proceed() throws Throwable {
   // We start with an index of -1 and increment early.
  // 如果没有拦截器执行执行目标方法,或者拦截器的索引和拦截器数组-1大小一样(指定到了最后一个拦截器)执行目标方法;
   if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
      return invokeJoinpoint();
   }

   Object interceptorOrInterceptionAdvice =
         this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
   if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
      // Evaluate dynamic method matcher here: static part will already have
      // been evaluated and found to match.
      InterceptorAndDynamicMethodMatcher dm =
            (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
      Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
      if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
         return dm.interceptor.invoke(this);
      }
      else {
         // Dynamic matching failed.
         // Skip this interceptor and invoke the next in the chain.
         return proceed();
      }
   }
   else {
      // It's an interceptor, so we just invoke it: The pointcut will have
      // been evaluated statically before this object was constructed.
     // 链式获取每一个拦截器,拦截器执行invoke方法,每一个拦截器等待下一个拦截器执行完成返回以后再来执行;
     // 拦截器链的机制,保证通知方法与目标方法的执行顺序;
      return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
   }
}

aop原理小结

  1. @EnableAspectJAutoProxy 开启AOP功能

  2. @EnableAspectJAutoProxy 会给容器中注册一个组件 AnnotationAwareAspectJAutoProxyCreator

  3. AnnotationAwareAspectJAutoProxyCreator是一个后置处理器;

  4. 容器的创建流程:

    1. registerBeanPostProcessors()注册后置处理器;创建AnnotationAwareAspectJAutoProxyCreator对象

    2. finishBeanFactoryInitialization()初始化剩下的单实例bean

      1. 创建业务逻辑组件和切面组件

      2. AnnotationAwareAspectJAutoProxyCreator拦截组件的创建过程

      3. 组件创建完之后,判断组件是否需要增强

        是:切面的通知方法,包装成增强器(Advisor);给业务逻辑组件创建一个代理对象(cglib);

  5. 执行目标方法:

    1. 代理对象执行目标方法
    2. CglibAopProxy.intercept();
      1. 得到目标方法的拦截器链(增强器包装成拦截器MethodInterceptor)
      2. 利用拦截器的链式机制,依次进入每一个拦截器进行执行;
      3. 效果:
        • 正常执行:前置通知-》目标方法-》后置通知-》返回通知
        • 出现异常:前置通知-》目标方法-》后置通知-》异常通知