Spring注解开发——28-35 Aop原理

目录

 

Aop原理:(spring原理都是看给容器注册了什么组件,这个组件什么时候工作,功能是什么)

1 @EnableAspectJAuoProxy注解向容器中注册AnnotationAwareAspectJAutoProxyCreator组件

    1.1 AspectJAutoProxyRegistrar registerBeanDefinitions() 实现的功能:

        1.1.1、registerAspectJAnnotationAutoProxyCreatorIfNecessary()方法

        1.1.2、获取注解上的属性,判断创建的内容

2、AnnotationAwareAspectJAutoProxyCreator到底是一个什么样的组件

    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此时被创建:

            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.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.1.2 判断当前bean是否是基础类型

            2.3.1.3 是否需要跳过

        2.3.2 调用postProcessAfterInitialization()生成代理类

            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判断)​

        最后给容器中返回当前组件MathCalculate使用cglib增强了的代理对象。然后当从容器中获取这个组件的时候,其实获取的是一个MathCalculate的代理类,当我们调用MathCalculate组件的方法时,其实是通过代理类去操控组件的方法,所以可以为组件功能增强

    2.4 目标方法执行--仍然会触发拦截器链

    ​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此时被创建

优先注册顺序:

  1. 创建实现了PriorityOrdered接口的BeanPostProcessor
  2. 创建实现了Ordered接口的BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator在这里
  3. 创建实现其他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()方法触发拦截器链,我们点击去看看里面的执行过程

在这里插入图片描述

下面画个图来说明一下拦截器链的触发过程

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值