目录
Aop原理:(spring原理都是看给容器注册了什么组件,这个组件什么时候工作,功能是什么)
1 @EnableAspectJAuoProxy注解向容器中注册AnnotationAwareAspectJAutoProxyCreator组件
1.1 AspectJAutoProxyRegistrar registerBeanDefinitions() 实现的功能:
1.1.1、registerAspectJAnnotationAutoProxyCreatorIfNecessary()方法
2、AnnotationAwareAspectJAutoProxyCreator到底是一个什么样的组件
2.1、容器启动AnnotationAwareAspectJAutoProxyCreator什么时候注入的
2.1.3 registerBeanPostProcessors(beanFactory);注册bean的后置处理器,方便拦截bean的创建
2.1.3.1 先获取IOC容器已经定义了的需要创建对象的所有的BeanPostProcessor。
2.1.3.2 给容器用加入别的BeanPostProcessor
2.1.3.3 按优先级创建BeanPostProcessor组件AnnotationAwareAspectJAutoProxyCreator此时被创建:
2.1.3.4 创建BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)对象;
2.1.3.4.2 populateBean给bean的属性赋值
2.1.3.4.3 initializeBean初始化bean
2.1.3.4.3.1 处理Aware接口的回调方法(回调setBeanFactory方法)
2.1.3.4.3.2 执行后置处理的postProcessBeforeInitialization()方法
2.1.3.5 把BeanPostProcessor注册到BeanFactory中
2.2 AnnotationAwareAspectJAutoProxyCreator组件的执行时机
2.2.1 InstantiationAwareBeanPostProcessor接口
2.2.1 普通单实例bean对象的创建是走refresh方法的finishBeanFactoryInitialization方法
2.2.3 AnnotationAwareAspectJAutoProxyCreator组件的执行时机分析
2.2.3.1 遍历获取容器中所有的Bean,依次创建对象getBean(beanName)。主要流程是getBean() -> doGetBean() -> getSingleton()
2.2.3.2 createBean()会在创建真正的bean之前调用resolveBeforeInstantiation() 方法生成bean对象,如有bean!=null后续不再创建bean对象。
2.2.3.3 resolveBeforeInstantiation() 调用所有InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation()方法创建代理类
到这里我们就知道了InstantiationAwareBeanPostProcessor组件即AnnotationAwareAspectJAutoProxyCreator组件执行postProcessBeforeInstantiation时机是在创建单实例之前
2.2.4 AnnotationAwareAspectJAutoProxyCreator会在后面创建单实例bean时调用beanPostProcessor方法postProcessAfterInstantiation
2.3 AnnotationAwareAspectJAutoProxyCreator组件的作用
2.3.1 postProcessBeforeInstantiation()
2.3.1.1 判断当前bean是否在advisedBeans中
2.3.2 调用postProcessAfterInitialization()生成代理类
2.3.2.2.3 将需要增强的bean保存在advisedBeans列表中
2.3.2.2.4 将需要增强的bean创建一个代理类(jdk或cglib,spring判断)
最后给容器中返回当前组件MathCalculate使用cglib增强了的代理对象。然后当从容器中获取这个组件的时候,其实获取的是一个MathCalculate的代理类,当我们调用MathCalculate组件的方法时,其实是通过代理类去操控组件的方法,所以可以为组件功能增强
2.5 拦截器链的触发过程画图解释
Aop原理:(spring原理都是看给容器注册了什么组件,这个组件什么时候工作,功能是什么)
1 @EnableAspectJAuoProxy注解向容器中注册AnnotationAwareAspectJAutoProxyCreator组件
点进@EnableAspectJAutoProxy注解的源码可以看到是使用@Import注解给我们向容器中注册了一个AspectJAutoProxyRegistrar的组件
那么AspectJAutoProxyRegistrar这个组件又是什么呢?我们再继续点进去看看,发现这个组件实现了ImportBeanDefinitionRegistrar接口。
前面我们学习@Import的时候理解到ImportBeanDefinitionRegistrar这个接口提供的registerBeanDefinitions()方法可以让我们进行手动注册一些组件到容器中去
然后我们看一下registerBeanDefinitions()这个方法里面做了一些什么操作
1.1 AspectJAutoProxyRegistrar registerBeanDefinitions() 实现的功能:
1.1.1、registerAspectJAnnotationAutoProxyCreatorIfNecessary()方法
功能是确保容器中含有
以org.springframework.aop.config.internalAutoProxyCreator 作为definination的名称的
org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator组件
1.1.2、获取注解上的属性,判断创建的内容
2、AnnotationAwareAspectJAutoProxyCreator到底是一个什么样的组件
....
↳ AbstractAutoProxyCreator
↳ AbstractAdvisorAutoProxyCreator
↳ AspectJAwareAdvisorAutoProxyCreator
↳ AnnotationAwareAspectJAutoProxyCreator
关注点:
- AbstractAutoProxyCreator.setBeanFactory
- AbstractAutoProxyCreator.后置处理器方
- AbstractAdvisorAutoProxyCreator.setBeanFactory ->initBeanFactory
- AnnotationAwareAspectJAutoProxyCreator.initBeanFactory
2.1、容器启动AnnotationAwareAspectJAutoProxyCreator什么时候注入的
2.1.1 传入配置类,创建IOC容器`
2.1.2 注册配置类,调用refresh()刷新容器
2.1.3 registerBeanPostProcessors(beanFactory);注册bean的后置处理器,方便拦截bean的创建
2.1.3.1 先获取IOC容器已经定义了的需要创建对象的所有的BeanPostProcessor。
2.1.3.2 给容器用加入别的BeanPostProcessor
2.1.3.3 按优先级创建BeanPostProcessor组件AnnotationAwareAspectJAutoProxyCreator此时被创建:
优先注册顺序:
- 创建实现了PriorityOrdered接口的BeanPostProcessor
- 创建实现了Ordered接口的BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator在这里)
- 创建实现其他BeanPostProcessor
2.1.3.4 创建BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)对象;
2.1.3.4.1 创建bean的实例
2.1.3.4.2 populateBean给bean的属性赋值
2.1.3.4.3 initializeBean初始化bean
2.1.4.3.1 处理Aware接口的回调方法(回调setBeanFactory方法)
2.1.4.3.2 执行后置处理的postProcessBeforeInitialization()方法
2.1.3.5 把BeanPostProcessor注册到BeanFactory中
2.2 AnnotationAwareAspectJAutoProxyCreator组件的执行时机
2.2.1 InstantiationAwareBeanPostProcessor接口
实现了InstantiationAwareBeanPostProcessor接口组件,在创建普通单实例bean对象的时候,会先调用组件的postProcessBeforeInstantiation()方法
2.2.1 普通单实例bean对象的创建是走refresh方法的finishBeanFactoryInitialization方法
2.2.3 AnnotationAwareAspectJAutoProxyCreator组件的执行时机分析
2.2.3.1 遍历获取容器中所有的Bean,依次创建对象getBean(beanName)。主要流程是getBean() -> doGetBean() -> getSingleton()
2.2.3.2 createBean()会在创建真正的bean之前调用resolveBeforeInstantiation() 方法生成bean对象,如有bean!=null后续不再创建bean对象。
2.2.3.3 resolveBeforeInstantiation() 调用所有InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation()方法创建代理类
到这里我们就知道了InstantiationAwareBeanPostProcessor组件即AnnotationAwareAspectJAutoProxyCreator组件执行postProcessBeforeInstantiation时机是在创建单实例之前,后面会将实例的代理对象放到advicebeans里面,这样就不需要再去制作代理类了
2.2.4 AnnotationAwareAspectJAutoProxyCreator会在后面创建单实例bean时调用beanPostProcessor方法postProcessAfterInstantiation
doCreateBean() 这个方法就是真正的开始创建bean了
2.3 AnnotationAwareAspectJAutoProxyCreator组件的作用
2.3 AnnotationAwareAspectJAutoProxyCreator组件的作用
上一节我们分析了在spring中创建所有的bean之前都会被AnnotationAwareAspectJAutoProxyCreator(InstantiationAwareBeanPostProcessor)组件的postProcessBeforeInstantiation()和postProcessAfterInstantiation()方法拦截,那么这两个方法到底做了什么呢?我们现在就开始拦截MathCalculator(目标类)组件和LogAspects(切面类)组件的创建
2.3.1 postProcessBeforeInstantiation()
每一个bean的创建都会被postProcessBeforeInstantiation()拦截,我们看一下里面做了什么?
其实创建普通的要被增强的目标类bean,该postProcessBeforeInstantiation无作用,下面进行解析:
2.3.1.1 判断当前bean是否在advisedBeans中
2.3.1.2 判断当前bean是否是基础类型
判断当前bean是否是基础类型其实就是判断当前组件的父类是否是Advice,Pointcut,Advisor,AopInfrastructureBean或是否为切面类即标注了@AspectJ注解
2.3.1.3 是否需要跳过
进入shouldSkip()方法
MathCalculate组件在上面的判断都是false,所以创建MathCalculate组件之前没有对其进行什么处理。然后开始创建MathCalculate组件调用doCreateBean,在初始化MathCalculate组件之后会被BeanPostProcessor组件的postProcessAfterInitialization()方法拦截,然后我们就分析一下postProcessAfterInitialization()方法里面操作
2.3.2 调用postProcessAfterInitialization()生成代理类
2.3.2.1 判断类是否需要包装,需要进行包装
2.3.2.2 包装过程
2.3.2.2.1 获取bean的所有增强器
2.3.2.2.2 对增强器排序
2.3.2.2.3 将需要增强的bean保存在advisedBeans列表中
2.3.2.2.4 将需要增强的bean创建一个代理类(jdk或cglib,spring判断)
进入getProxy()方法
继续进入createAopProxy()方法,我们可以看到有两种方法动态的创建代理类:1)通过jdk提供的api,这种方式要求被代理的类必须要实现一个接口;2)Cglib的方式。
最后给容器中返回当前组件MathCalculate使用cglib增强了的代理对象。然后当从容器中获取这个组件的时候,其实获取的是一个MathCalculate的代理类,当我们调用MathCalculate组件的方法时,其实是通过代理类去操控组件的方法,所以可以为组件功能增强
2.4 目标方法执行--仍然会触发拦截器链
上面我们知道AnnotationAwareAspectJAutoProxyCreator组件作为一个BeanPostProcessor在MathCalculate初始化之后,调用其postProcessAfterInitialization()方法判断MathCalculate组件需要增强吧,如果需要增强,那么就给MathCalculate组件创建了代理对象,下面我们从容器中获取MathCalculate组件,然后执行它的方法。
下面执行MathCalculate组件的div()方法,看看里面是怎么执行那些切面的通知方法的?首先是被CglibAopProxy的intercept()拦截
我们再看一下获取拦截器链的方法
判断拦截器链是否为空作出相应处理
2.5 拦截器链的触发过程
然后将拦截器链封装到CglibMethodInvocation中,调用proceed()方法触发拦截器链,我们点击去看看里面的执行过程
下面画个图来说明一下拦截器链的触发过程