zoukankan      html  css  js  c++  java
  • Spring源码窥探之:注解方式的AOP原理

    AOP入口代码分析

    通过注解的方式来实现AOP
    
    1. @EnableAspectJAutoProxy通过@Import注解向容器中注入了AspectJAutoProxyRegistrar这个类,而它在容器中的名字是org.springframework.aop.config.internalAutoProxyCreator。
    
    2. AspectJAutoProxyRegistrar实现了ImportBeanDefinitionRegistrar接口,所以可以向容器中注册Bean的定义信息。
    
    3. 通过跟踪AspectJAutoProxyRegistrar,我们发现它向容器中注册了AnnotationAwareAspectJAutoProxyCreator的定义信息。
    
    4. 观察AnnotationAwareAspectJAutoProxyCreator的继承结构图,发现,它既是一个后置处理器,又是一个BeanFactoryAware的实现类。
    
    所以我们可以分析:
    
    一、 AnnotationAwareAspectJAutoProxyCreator作为后置处理器做了什么?
    
    二、 作为Aware做了什么?

    继承结构分析

    AnnotationAwareAspectJAutoProxyCreator的继承结构图,如下:
    
    AnnotationAwareAspectJAutoProxyCreator
        -> extends AspectJAwareAdvisorAutoProxyCreator
            -> extends AbstractAdvisorAutoProxyCreator
                -> extends AbstractAutoProxyCreator
                    -> implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware
                       【可见AnnotationAwareAspectJAutoProxyCreator是一个后置处理器,也是一个Aware】
    
    AbstractAutoProxyCreator作为一个抽象类,实现了SmartInstantiationAwareBeanPostProcessor和BeanFactoryAware
    故,我们分别在他们的实现方法上加断点,比如:postProcessBeforeInstantiation()和setBeanFactory()

     断点调试

    首先来到AbstractAutoProxyCreator的setBeanFactory(),查看IDE的调用栈,如图:

    1. 传入配置类,创建IOC容器
    2. 注册配置类,调用refresh()刷新容器
    3. registerBeanPostProcessors(beanFactory)注册Bean的后置处理器,来拦截Bean的创建。
        1) 先获取IOC容器已经定义了的需要创建对象的所有BeanPostProcessor
        2) 给容器中添加另外其他的BeanPostProcessor
        3) 优先注册实现了PriorityOrdered接口的BeanPostProcessor
        4) 再注册实现Order接口的BeanPostProcessor
        5) 最后注册没实现任何接口的BeanPostProcessor
        6) 注册BeanPostProcessor,实际上就是创建BeanPostProcessor对象,并保存在容器中
           如何创建名字叫internalAutoProxyCreator【AnnotationAwareAspectJAutoProxyCreator】的后置处理器?
           1) 先来创建Bean的实例
           2) populateBean()给Bean的属性赋值
           3) initializeBean()初始化Bean
              1) invokeAwareMethods(beanName, bean)处理Aware接口的方法回调
              2) applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName)
                 拿到所有的BeanPostProcessor并执行postProcessBeforeInitialization
              3) invokeInitMethods(beanName, wrappedBean, mbd)执行自定义的初始化方法,比如init()和destroy()
              4) applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName)
                 拿到所有的BeanPostProcessor并执行postProcessAfterInitialization
           4) BeanPostProcessor【AnnotationAwareAspectJAutoProxyCreator】创建成功
        7) 把BeanPostProcessor注册并添加到BeanFactory中
    
    ==========以上是创建和注册AnnotationAwareAspectJAutoProxyCreator的过程==========

     AnnotationAwareAspectJAutoProxyCreator作为后置处理器做了什么?

    4. finishBeanFactoryInitialization(beanFactory)完成BeanFactory的初始化工作,创建剩下的单实例Bean
        1)遍历获取所有的Bean,依次创建对象getBean(beanName)
           getBean -> doGetBean() -> getSingleton()
        2)如何创建Bean?
           【首先说明:上面注册过的后置处理器AnnotationAwareAspectJAutoProxyCreator会在所有Bean创建之前进行拦截调用,因为
             AnnotationAwareAspectJAutoProxyCreator实现了InstantiationAwareBeanPostProcessor接口】
           1)先从缓存中获取当前Bean,如果能获取到,说明Bean是之前被创建过了的,直接使用,否则再进行创建
              只要被创建过的Bean都会被缓存起来
           2)createBean()创建Bean的实例,过程如下:
              1)resolveBeforeInstantiation(beanName, mbdToUse)这一步是尝试返回Bean的代理对象
                 希望后置处理器在此能返回一个代理对象,如果不能就调用doCreateBean()创建对象
                 如何返回代理对象呢?
                 if (targetType != null) {
                    bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                    if (bean != null) {
                        bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                    }
                 }
                 【注意:这里的applyBeanPostProcessorsBeforeInstantiation不同于BeanPostProcessor的postProcessBeforeInitialization】
                 【applyBeanPostProcessorsBeforeInstantiation和applyBeanPostProcessorsAfterInitialization属于InstantiationAwareBeanPostProcessor的方法
                    而InstantiationAwareBeanPostProcessor是在创建Bean对象实例之前进行调用,目的是在创建Bean对象之前首先尝试返回代理对象,
                    但BeanPostProcessor的两个方法则是在Bean对象创建完成,进行初始化的前后才进行调用,他们两个执行的时机不一样BeanPostProcessor的执行稍微晚一点】
              2)doCreateBean(beanName, mbdToUse, args)此方法才是真正的创建一个Bean实例,创建实例的流程和上面一样

    分析InstantiationAwareBeanPostProcessor的两个方法

    AnnotationAwareAspectJAutoProxyCreator实现了InstantiationAwareBeanPostProcessor所以每一个Bean在创建之前,都会经过
    postProcessBeforeInstantiation()方法。当然也包括被切的实体。
    
    1. 每个Bean在创建之前都会经过postProcessBeforeInstantiation()过程分析:
       1)判断当前Bean是否在advisedBeans(里面保存了需要增强的Bean)中。
          this.advisedBeans.containsKey(cacheKey)
       2)判断当前Bean是否是基础类型(Advice,Pointcut,Advisor,AopInfrastructureBean)。
          isInfrastructureClass(beanClass)
       3)是否需要跳过?(好像永远要跳过^_^)
          shouldSkip(beanClass, beanName)
          这个方法首先获取候选的增强器List<Advisor> candidateAdvisors = findCandidateAdvisors();
          每一个Advisor的类型是InstantiationModelAwarePointcutAdvisor,并不是AspectJPointcutAdvisor
    
    2. 经过postProcessBeforeInstantiation()尝试创建对象出来以后,进入AbstractAutoProxyCreator的postProcessAfterInitialization方法
       postProcessAfterInitialization方法中有一个wrapIfNecessary(bean, beanName, cacheKey)开始进行包装Bean,点击进入:
       1)Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
          找到所有的增强器,并获取到能在该Bean使用的增强器,然后顺便排序(目的是为了有序的切入)
       2)保存当前Bean到advisedBeans中
          this.advisedBeans.put(cacheKey, Boolean.TRUE)
       3)如果当前Bean需要增强,就创建当前Bean的代理对象
          Object proxy = createProxy(...),如何创建?如下:
          1. 获取所有通知方法
          2. 保存到proxyFactory中
          3. 创建代理对象,Spring自动决定
             new JdkDynamicAopProxy(config);实现接口
             ObjenesisCglibAopProxy(config);没有实现接口
       4)通过以上三步,wrapIfNecessary()方法会返回一个代理Bean并且放到容器中,当调用目标方法的时候,实际上是代理类在调用
  • 相关阅读:
    java处理特殊时间格式,2019-11-28T06:52:09.724+0000 转为常见格式2019-11-28 06:52:09,同时转为数据库日期格式Timestamp
    最近比较忙,处理项目上各种问题。此时有新任务来临,赶时间记录一个方法,加深对数组的理解
    springboot项目通过gradle运用capsule插件打可执行jar包
    HanLP 关键词提取。总结
    mmdet阅读笔记
    mmcv阅读笔记
    Monocular Real-time Hand Shape and Motion Capture using Multi-modal Data
    3D Hand Shape and Pose from Images in the Wild
    End to end recovery of human shape and pose
    工作小结五
  • 原文地址:https://www.cnblogs.com/zhangjianbing/p/10250674.html
Copyright © 2011-2022 走看看