首页>>后端>>Spring->spring的AOP原理

spring的AOP原理

时间:2023-11-30 本站 点击:0

概述

本期主要研究一下Spring底层是如何实现AOP的

EnableAspectJAutoProxy

都知道想要实现AOP必须先写一个@EnableAspectJAutoProxy注解,那么我们就先来看这个注解做了什么事情

注解上直接@Import了另一个类

@Import注解在spring容器解析的时候会被ConfigurationClassPostProcessor解析并且直接调用 registerBeanDefinitions接口的方法,这个已经在第一章分析过了,所以Import的这个类其实就是调用了一个AopConfigUtils的方法并且把容器传进去了

最终其实就是向容器中注册了一个 AnnotationAwareAspectJAutoProxyCreator对象

总结

我们添加的注解其实就是通过@Import的方式注入了一个其他的组件,我们在编码的过程中如果想实现什么功能也可以模仿spring的方式通过自定义注解在内部import组件来达到比较优雅的开启方式

AnnotationAwareAspectJAutoProxyCreator

我们来看这个bean在spring中都做了什么事情也就知道AOP的原理了。

初始化

因为这个Bean是一个后置处理器跟别的普通容器不一样,spring会优先创建后置处理器对象

然后就走正常的spring获取对象的流程,在实例化完spring对象之后,有一个执行生命周期函数的地方,因为AnnotationAwareAspectJAutoProxyCreator是一个BeanFactoryAware所以执行生命周期方法

在生命周期方法内创建了一个builder和一个工厂

组件在spring容器中的作用

因为是一个后置处理器,所以在其他bean创建的时候会调用该后置处理器的方法,我们来看看。

postProcessBeforeInstantiation

在bean创建对象之前会先调用该方法,如果返回对象则spring容器不会再自己创建对象 我们可以看到在方法中进行了一个或的判断,所以只要是前面的为true则就会被加入到一个map中,前面的判断是判断正在创建的对象是不是一个切面类

inInfrastructureClass 如果类上有 @Aspect 注解就会被加入到advisedBeans这个map中,并且value是false

shouldSkip

shouldSkip的返回值并不重要,我们看方法内做了什么事情

我们来看看是如何获得增强器列表的

可以看到先调用父类的方法获取了一个list,其实是空的然后在调用自己的builder返回一个list.自然看builder的成声逻辑 通过代码可以看到,在第一次调用build的时候,aspectBeanNames是空的,所以会遍历整个spring容器中的所有对象然后找到切面类,在吧切面类中的增强方法找出来缓存住然后返回.我们来看看spring是如何判断切面类中的增强方法的. 可以看到,spring是把切面类的每一个方法都遍历过去,判断是不是切面类 上面的方法没什么好看的,就是方法传进来尝试生成一个对象,如果可以生成就返回,最后就是由 AbstractAspectJAdvisorFactory判断能不能生成对象.

postProcessBeforeInstantiation总结

AOP在该方法中就是做了两个事情

把所有的切面类都保存在了一个 advisedBeans map里面,并且value是false

初始化了所有切面类和其增强方法的一个缓存

postProcessAfterInitallization

在spring创建完bean对象并且属性赋值结束后,调用postProcessAfterInitallization,AOP组件又做了一些事情.生命周期流程如图

方法中调用了一个 wrapIfNecessary,顾名思义如果满足条件就创建一个代理包装类,AOP的代理对象就是在这个时候创建的

我们先来看spring是如何判断一个bean有没有切面需要对其进行增强的 由于在之前的shouldSkip方法中,spring已经遍历过所有的切面类,并且缓存了他们和增强器的映射,所以拿到所有的增强器其实就是从缓存中获取 判断增强器是不是命中目标bean,则是通过 AopUtils来实现 这个类里面就比较复杂,代码贴出来太麻烦 在返回了命中的增强器之后,如果有数据spring还会添加一个增强器到队列头部!!!

2. 知道了spring是如何判断一个类需不需要增强之后,我们来看如果有增强方法spring是如何生产代理对象的

在生成代理对象的时候还会判断是使用 JDK的动态代理还是cglib

返回了一个enhancer

我们看到在增强方法中把切面方法 advised包裹成DynamicAdvisedInterceptor

AOP方法调用过程

springboot2.x现在的动态代理是GCLIB的形式,所以调用的时候是走到DynamicAdvisedInterceptorintercept方法

生成拦截器

我们先来看生成拦截器的逻辑,spring把容器中所有增强器遍历去生成拦截器 生成拦截器的逻辑是把增强器中的增强方法取出来,判断是不是MethodInterceptor如果不是,也还有对应的Apater进行转换成拦截器 增强器获得增强方法的逻辑在ReflectiveAspectJAdvisorFactory方法中,每个不同的切面都会生成不同的advise

Proceed

生成完拦截器之后就开始调用Proceed方法CglibMethodInvocationReflectiveMethodInvocation 的子类重点逻辑都在 父类维护了一个index的索引和一个拦截器链,在之前创建切面类的时候,spring首先放入了一个写死的切面类

这个增强器在的advise是ExposeInvocationInterceptor 所以在执行proceed的时候第一个执行的就是spring提供的增强,方法中通过一个threadLocal把对象保存起来,然后继续调用proceed方法 这时候方法又回到了ReflectiveMethodInvocation类中,不同的是 index索引增加了,所以取出下一个拦截器链继续执行,AOP通过一个index和链条的方式把AOP的前置后置异常等切面串再了一起


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:/Spring/4483.html