AOP原理(都是干货)

218 阅读5分钟

1. 什么是EnableAspectJAutoProxy

@Import({AspectJAutoProxyRegistrar.class}),给容器中导入AspectJAutoProxyRegistrar,然后自定义注册到容器中的bean,并且判断是否要注册internalAutoProxyCreator,而AnnotaionAwareAspectJAutoProxyCreator实际上是实现了BeanPostProcessor(bean的后置处理器),在bean的初始化前后会调用逻辑,并且它也实现了BeanFactoryAware,可以实现setBeanFactory方法

AnnotationAwareAspectJAutoProxyCreator.png

2. AnnotaionAwareAspectJAutoProxyCreator

2.1 实现了BeanPostProcessor

AbstractAutoProxyCreator实现了postProcessBeforeInstantiation()方法以及postProcessAfterInstantiation,并在其子类中沿用

2.2 实现了BeanFactoryAware接口

  1. AbstractAutoProxyCreator实现了setBeanFactory()方法,
  2. AbstractAdvisorAutoProxyCreator继承了AbstractAutoProxyCreator,并重写了setBeanFactory方法,并且调用了一个initBeanFactory方法
  3. AnnotationAwareAspectJAutoProxyCreator继承了AbstractAdvisorAutoProxyCreator,并重写了initBeanFactory方法

2.3 initBeanFactory方法

2.3.1. 传入配置类,创建IOC容器

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

2.3.3. registerBeanPostProcessor()注册bean的后置处理器

  1. 先获取ioc容器所有已经定义的BeanPostProcessor
  2. 给容器中添加其他的BeanPostProcessor
  3. 优先注册实现了ProrityOrdered接口的BeanPostProcessor
  4. 然后注册实现了Ordered接口的BeanPostProcessor
  5. 注册没实现优先级接口的BeanPostProcessor
  6. 创建BeanPostProcessor对象到容器中
    1. 创建Bean的实例
    2. 给bean的属性赋值,populatebean
    3. 初始化bean initializingBean
      1. invokeAwareMethods(),处理aware接口的方法回调
      2. applyBeanPostProcessorBeforeInitialization,调用BeanPostProcessor的初始化前的操作
      3. invokeInitMethod()执行自定义的初始化方法
      4. applyBeanPostProcessorBeforeInitialization,调用BeanPostProcessor的初始化后的操作
      5. 调用setBeanFactory方法
      AbstractAutowireCapableBeanFactory#invokeAwareMethods
      //调用XXXAware接口的回调方法,这里一次判断当前bean是否是XXXAware接口的实例并触发其回调方法
        private void invokeAwareMethods(String beanName, Object bean)   {
      if (bean instanceof Aware) {
      if (bean instanceof BeanNameAware) {
          ((BeanNameAware)bean).setBeanName(beanName);
      }
      
      if (bean instanceof BeanClassLoaderAware) {
          ClassLoader bcl = this.getBeanClassLoader();
          if (bcl != null) {
              ((BeanClassLoaderAware)bean).setBeanClassLoader(bcl);
          }
      }
      
      if (bean instanceof BeanFactoryAware) {
          ((BeanFactoryAware)bean).setBeanFactory(this);
      }
      }
      
      }
      
    4. AnnotationAwareAspectJAutoProxyCreator创建成功
  7. 给BeanPostProcessor注册到BeanFactory里面

2.3.4. 调用AbstractApplicationContext#finishBeanFactoryInitialization方法,完成BeaFactory方法初始化

  1. 遍历容器中的所有Bean,依次通过getBean方法创建对象 getBean-> doGetBean-getSingleton,众所周知,spring中doXXX()才是实际处理的方法。

  2. 创建Bean AnnotationAwareAspectJAutoProxyCreator在所有Bean实例创建之前会拦截,并调用AbstractAutoProxyCreator#postProcessBeforeInstantiation的方法

    1. 先从缓存中获取Bean,如果能够获取得到,说明是之前创建的,直接使用,否则创建,只要创建好的bean都会被缓存起来
    2. createBean 创建Bean BeanPostProcessor是在Bean对象创建完成初始化前后调用的,而InstantiationAwareBeanPostProcessor是在创建Bean实例之前先尝试用后置处理器处理
      beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);
      if (beanInstance != null) {
          return beanInstance;
      }
      
      resolveBeforeInstantiation在这里希望返回一个代理对象,如果能返回代理对象就直接使用,不能就再次调用doCreateBean
    3. 后置处理器尝试返回对象
      AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInstantiation //如果实现了InstantiationAwareBeanPostProcessor,则需要进行AOP代理 if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp; Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName); if (result != null) { return result; } } 判断是否是InstantiationAwareBeanPostProcessor的实例,如果是就执行postProcessBeforeInstantiation方法
    4. doCreateBean 真正的去创建一个实例

2.4 InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法的作用

2.4.1. 每一个Bean创建之前,调用postProcessBeforeInstantiation方法

  1. 判断当前bean是否在advisedBeans中
  2. 判断当前bean是否是基础类型的(Advice,Advisor,AopInfrastrucatureBean)
  3. 判断是否需要跳过
    1. 获取候选的增强器(即切面方法),判断增强器的类型是否是AspectJPointcutAdvisor

2.4.2. 创建完对象,调用postProcessAfterInstantiation方法

  1. wrapIfNecessary(Object bean, String beanName, Object cacheKey)
    1. 获取当前的所有增强器(切面方法)
    2. 找到能在当前bean使用的通知方法(即哪些方法是需要切入的)
    3. 给可用的增强器进行排序
  2. 保存当前Bean到advisedBeans中
  3. 如果bean需要增强,创建代理对象
    1. 获取所有增强器
    2. 保存到proxyFactory
    3. 创建代理对象,由Spring来决定创建Cglib的动态代理还是JDK的动态代理
  4. 给容器中返回已经被Cglib代理增强后的对象
  5. 以后容器中获取到的是代理对象,执行目标方法的时候,代理对象就会执行通知方法

2.4.3. 目标方法执行

容器中保存了组件的代理对象(cglib增强后的对象),这个对象保存了所有的增强器、目标对象信息 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

  1. 进入到CglibProxy#intercept方法,拦截目标方法的执行
  2. 根据ProxyFactory对象获取目标方法拦截器链
    1. 遍历所有的增强器,将其转为Interceptor,这其中用到了适配器将增强器转为Interceptor
    2. 如果没有拦截器链,直接执行目标方法 拦截器链实际上每一个通知方法被包装为拦截器,利用MethodInterceptor机制
    3. 如果由拦截器链,把需要执行的目标对象的目标方法以及拦截器链等信息创建一个CglibMethodInvocation对象并调用它的proceed方法
    4. 拦截器链的触发过程:
      1. 如果没有拦截器,直接执行目标方法,或者拦截器的当前索引等于拦截器数组大小减一,也会执行目标方法
      2. 链式获取每一个拦截器,拦截器执行invoke方法,每一个拦截器等待下一个拦截器执行完成返回然后再执行,责任链模式来保证通知方法的执行顺序

3. 总结

  1. 利用EnableAspectJAutoProxy开启AOP功能
  2. EnableAspectJAutoProxy会给容器注册一个AnnotaionAwareAspectJAutoProxyCreator
  3. 而AnnotaionAwareAspectJAutoProxyCreator是一个BeanPostProcessor(后置处理器)
  4. 容器的创建过程中:AbstractApplicationContext#refresh方法
    1. registerBeanPostProcessor()注册后置处理器
    2. finishBeanFactoryInitialization初始化剩下的单实例Bean
      1. 创建业务逻辑组件和切面组件
      2. AnnotaionAwareAspectJAutoProxyCreator 拦截组件的创建过程
      3. 组件创建完之后判断是否需要增强
      4. 如果需要增强(切面的通知方法),包装成增强器(advisor)
      5. 给业务组件创建一个代理对象
  5. 执行目标方法
    1. 代理对象执行目标方法
    2. CglibAopProxy#intercept方法拦截
      1. 通过包装增强器得到目标方法的拦截器链(MethodInterceptor数组,这个数组安装执行顺序的倒序排序)
      2. 利用拦截器的链式机制,逐一进入每一个拦截器进行执行
      3. 正常结果 前置通知 -> 目标方法 -> 后置通知 -> 返回通知
      4. 异常结果 前置通知 -> 目标方法 -> 后置通知 -> 异常通知