Spring源码窥探之:注解方式的AOP原理

AOP入口代码分析

通过注解的方式来实现AOP1. @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并且放到容器中,当调用目标方法的时候,实际上是代理类在调用

原文地址:https://www.cnblogs.com/zhangjianbing/p/10250674.html

时间: 2024-10-30 03:18:34

Spring源码窥探之:注解方式的AOP原理的相关文章

Spring源码窥探之:@Profile

Spring为我们提供的多环境启动 1. 配置类,注入三个不同环境的数据源,并加上注解 /** * description: 以下准备了三套不同环境的数据源 * * @author 70KG * @date 2018/12/17 */ @Configuration public class MyConfig { @Bean @Profile("dev") public MySqlInfo mySqlInfoDev() { MySqlInfo mySqlInfo = new MySqlI

Spring源码窥探之:声明式事务

1. 导入驱动,连接池,jdbc和AOP的依赖 <!-- c3p0数据库连接池 --> <dependency> <groupId>c3p0</groupId> <artifactId>c3p0</artifactId> <version>0.9.1.2</version> </dependency> <!-- spring提供的jdbcTemplate模块 --> <depend

Spring源码窥探之:Spring IOC之@Value

1. 首先定义实体 /** * @author 70KG * @Title: Apple * @Description: 苹果实体 * @date 2018/10/22下午9:26 * @From www.nmyswls.com */ @Data public class Apple { @Value("${apple.color}") private String color; @Value("红富士") private String name; } 2. 属性文

Spring源码窥探之:ImportSelector

1. 编写实现ImportSelector的类 /** * @author 70KG * @Title: SelectImportBean * @Description: * @date 2018/7/22下午4:59 * @From www.nmyswls.com */ public class SelectImportBean implements ImportSelector { @Override public String[] selectImports(AnnotationMetad

spring源码剖析(六)AOP实现原理剖析

Spring的AOP实现原理,酝酿了一些日子,写博客之前信心不是很足,所以重新阅读了一边AOP的实现核心代码,而且又从网上找了一些Spring Aop剖析的例子,但是发现挂羊头买狗肉的太多,标题高大上,内容却大部分都是比较浅显的一些介绍,可能也是由于比较少人阅读这部分的核心代码逻辑把,然后写这部分介绍的人估计也是少之又少,不过说实话,Spring Aop的核心原理实现介绍确实不太好写,里面涉及的类之间的调用还是蛮多的,关系图画的太细的画也很难画,而且最重要的一点就是,如果对AOP的概念以及spr

spring源码分析

spring源码剖析(九)springMVC源码剖析 springMVC 相信大伙都用过,但是spring框架对于你请求的一个url 到你看到的返回结果,期间做了哪些出来呢,文件上传的封装?controller的寻找?过滤器的调用?AOP的调用?视图的解析?页面的跳转?  这些过程具体是怎么实现的,下面我们一一来向大家介绍springMVC的架构.... 2017-02-26 14:02 阅读(248) 评论(0) spring源码剖析(八)spring整合mybatis原理 MyBatis相信

Spring 源码(九)@Autowired注解实现原理(Spring Bean的自动装配

@Autowired注解的实现过程,其实就是Spring Bean的自动装配过程.通过看@Autowired源码注释部分我们可以看到@Autowired的实现是通过AutowiredAnnotationBeanPostProcessor后置处理器中实现的. AutowiredAnnotationBeanPostProcessor 类图 PriorityOrdered:确认 AutowiredAnnotationBeanPostProcessor 后置处理器的执行优先级 BeanFactoryAw

Spring 源码(九)@Autowired注解实现原理(Spring Bean的自动装配)

@Autowired注解的实现过程,其实就是Spring Bean的自动装配过程.通过看@Autowired源码注释部分我们可以看到@Autowired的实现是通过AutowiredAnnotationBeanPostProcessor后置处理器中实现的. AutowiredAnnotationBeanPostProcessor 类图 PriorityOrdered:确认 AutowiredAnnotationBeanPostProcessor 后置处理器的执行优先级BeanFactoryAwa

Spring IoC 源码分析 (基于注解) 之 包扫描

在上篇文章Spring IoC 源码分析 (基于注解) 一我们分析到,我们通过AnnotationConfigApplicationContext类传入一个包路径启动Spring之后,会首先初始化包扫描的过滤规则.那我们今天就来看下包扫描的具体过程. 还是先看下面的代码: AnnotationConfigApplicationContext类 //该构造函数会自动扫描以给定的包及其子包下的所有类,并自动识别所有的Spring Bean,将其注册到容器中 public AnnotationConf