Spring AOP之AopProxy代理对象

Spring AOP之AopProxy代理对象,第1张

在Spring的AOP模块,一个主要的部分是代理对象的生成,可以通过ProxyFactoryBean来完成,它封装了主要代理对象的生成过程。在这个生成过程中,可以使用JDK的Proxy和CGLIB两种生成情况。

Tip: 什么是匿名类

即没有名称的类,其名称由Java编译器给出,一般为:外部类名称+$+匿名类顺序,名称也就是其他地方不能引用,不能实例化,只用一次,当然也就不能有构造器。

在ProxyFactoryBean中,需要为target目标对象生成Proxy代理对象,从而为AOP横切面的编织做好准备。从FactoryBean中获取对象,是以getObject()方法作为入口完成的。在该方法中,首先对通知器链进行初始化,封装了一系列的拦截器,这些拦截器都要从配置中读取,然后为代理对象的生成做好准备。在生成代理对象时,因为Spring中有singleton类型和prototype类型这两种不同的Bean,所以要对代理对象的生成做一个区分。

首先为Proxy代理对象配置Advisor链,在initializeAdvisorChain()方法中执行。

在该方法中它会首先通过thisadvisorChainInitialized来判断通知器链是否已经初始化了,如果已经初始化了,就直接返回。其他情况下,通过 thisinterceptorNames 来要添加的通知器名,然后通过该名从IOC容器中取得的通知器加入到拦截器链中。

生成singleton的代理对象在getSingletonInstance()中完成

如果它还没有被创建,则lazily creating

在Spring代理目标target时,其实并不是直接创建一个目标target的对象实例的,而是通过一个TargetSource类型的对象对目标target进行封装,Spring Aop获取目标对象始终是通过 TargetSourcegetTarget() 方法进行的。

proxy(代理对象)代理的不是target,而是TargetSource

那么问题来了:为什么SpringAOP代理不直接代理target,而需要通过代理TargetSource(target的来源,其内部持有target),间接代理target呢

通常情况下,一个proxy(代理对象)只能代理一个target,每次方法调用的目标也是唯一固定的target。但是,如果让proxy代理TargetSource,可以使得每次方法调用的target实例都不同(当然也可以相同,这取决于TargetSource实现)。这种机制使得方法调用变得灵活,可以扩展出很多高级功能,如:target pool(目标对象池)、hot swap(运行时目标对象热替换),等等。

Spring内置了多种TargetSource

监听调用AdvisedSupportListener实现类的activated方法

具体的代理对象的生成,是在ProxyFactoryBean的基类AdvisedSupport的实现中借助AopProxyFactory完成的,这个代理对象要么从JDK中生成,要么借助CGLIB获得。

这个AopProxyFactory是在初始化函数中定义的,使用的是DefaultAopProxyFactor。

如果targetClass是接口类,使用JDK来生成Proxy

如果不是接口类要生成Proxy,那么使用CGLIB来生成。

接下来分别介绍两种不同的方式来产生AopProxy代理对象

首先从advised对象中取得代理对象的代理接口配置,然后调用Proxy的newProxyInstance方法,得到最终的Proxy代理对象。

在生成代理对象时,需要指明三个参数,类加载器,代理接口和Proxy回调方法所在的对象。

在回调方法所在对象中,需要实现InvocationHandler接口,它定义了invoke方法,

对于JdkDynamimcAopProxy,它本身实现了InvocationHandler接口和invoke方法,这个invoke方法是Proxy代理对象的回调方法。

在该篇文章中就不讲解了,感兴趣的可以百度搜索。

注:本文大多数是对《Spring技术内幕》的阅读整理。

下图是AOP自动代理的流程图

spring中已经定义了创建代理的工厂类 ProxyFactory,通过 ProxyFactory 创建代理,必须要一个被代理对象和一个增强Advisor列表

spring的动态代理实质就是对象创建完毕之后,查找筛选能够应用于该对象上的Advisor列表,然后调用ProxyFactory创建代理对象返回。

Spring中定义了 AbstractAutoProxyCreator 类用于实现自动代理。

从继承图可以看出该类实现了 BeanPostProcessor 接口,覆写了postProcessAfterInitialization 方法。spring的bean初始化完成后会遍历注册的所有BeanPostProcessor实现类对象,调用其postProcessAfterInitialization方法,该方法可以返回一个新的对象覆盖原有对象,在此spring提供一个创建代理并覆盖被代理对象的机会

遍历容器中注册的所有BeanPostProcessor,调用postProcessAfterInitialization方法,如果返回一个新的对象会覆盖掉原始对象注册到spring容器中

上面分析了AbstractAutoProxyCreator是实现自动代理的关键,那么在spring中如何配置一个AbstractAutoProxyCreator的实现类对象呢,spring又是如何根据配置注册该对象的

在spring中可以通过两种配置,启动自动代理

这两中方法最终都是向spring容器中注册了一个AnnotationAwareAspectJAutoProxyCreator实例,这样在spring初始化完对象后就可以调用AnnotationAwareAspectJAutoProxyCreator的postProcessAfterInitialization方法了

上面分析了spring是在何时何处开始创建代理的,解下来分析AbstractAutoProxyCreator进行自动代理的总体实现

在postProcessAfterInitialization方法中判断 被代理对象不为空,调用wrapIfNecessary判断是否对目标类进行代理

createProxy方法中通过ProxyFactory设置AOP配置,如被代理对象和Advisor列表,调用getProxy创建代理对象。

至此AbstractAutoProxyCreator完成了自动创建代理的总体实现,在该抽象类中没有实现获取Adviso列表r的功能,交由各个子类去实现。

分析完spring自动代理的整体实现,接下来看下AbstractAutoProxyCreator的子类AbstractAdvisorAutoProxyCreator是如何进行查找 Advisor、筛选Advisor、排序Advisor的。

AbstractAdvisorAutoProxyCreator实现了getAdvicesAndAdvisorsForBean方法,用于获取应用于目标类的Advisor列表

在findEligibleAdvisors方法定义了查找 Advisor、筛选Advisor、排序Advisor三步 *** 作

在spring中可以通过注册Advisor的bean来实现对目标类的增强代理。spring会筛选出容器中所有Advisor类型的bean,用于对容器中的对象进行增强代理,查找的功能由AbstractAdvisorAutoProxyCreator类实现

将查找功能委托给advisorRetrievalHelper(BeanFactoryAdvisorRetrievalHelperAdapter)实现,该方法的功能就是获取Advisor类型的bean对象返回

spring除了支持配置或者手动注册 Advisor类型的bean之外,还支持通过 @Aspect、@Before、@After等AOP注解来声明Advisor。Advisor的查找解析由子类AnnotationAwareAspectJAutoProxyCreator实现

在AnnotationAwareAspectJAutoProxyCreator的findCandidateAdvisors方法中,第一步首先调父类的方法获取到容器中注册的所有Advisor,然后再委托aspectJAdvisorsBuilder解析注解获取Advisor,然后合并两个结果返回

BeanFactoryAspectJAdvisorsBuilderbuildAspectJAdvisors方法解析AOP注解封装为Advisor对象。

spring定义了一个AspectJAdvisorFactory接口用于解析AOP的注解,接口主要定义了两个功能

AspectJAdvisorFactory的实现类ReflectiveAspectJAdvisorFactory提供了具体实现

调用getAdvisor方法,获取通知方法上的Pointcut表达式,如果在方法上未解析到Pointcut,则跳过,然后根据通知方法和对应Pointcut封装返回一个Advisor的实现类InstantiationModelAwarePointcutAdvisorImpl对象

解析获取通知方法的Pointcut表达式,在该方法中会过滤掉不带Aop注解的非通知型方法,判断一个方法是不是通知就是判断该方法是否声明了切点

最终封装返回的Advisor是InstantiationModelAwarePointcutAdvisorImpl类型,在该实现类的getAdvice方法会回调ReflectiveAspectJAdvisorFactory中的getAdvice方法,ReflectiveAspectJAdvisorFactory会根据通知方法上不同的注解,创建对应的Advice

回调ReflectiveAspectJAdvisorFactory中的getAdvice,策略创建对应的Advice实现类对象

获取到spring容器中所有的Advisor之后,再回到AbstractAdvisorAutoProxyCreator类中,接下来筛选能够应用到目标对象的Advisor。通过Advisor中的Pointcut的ClassFilter和MethodMatcher来对目标对象进行匹配。 在这个阶段的筛选,只要Advisor能应用到目标类型的任意一个方法上都会返回成功

接下来看AbstractAdvisorAutoProxyCreatorfindAdvisorsThatCanApply方法,将筛选的工作委托给AopUtils来实现

AopUtilsfindAdvisorsThatCanApply方法中遍历所有的Advisor,然后调用canApply方法判断是否符合,在当中会区分引介增强和切点增强,引介增强是类级别的,只需要根据切点的ClassFilter对目标类进行判断就行。

canApply方法中,通过Pointcut来进行匹配,引介增强IntroductionAdvisor直接根据其ClassFilter判断目标类型,PointcutAdvisor根据其中的Pointcut来进行筛选

Pointcut会首先使用ClassFilter对目标类型进行过滤。如果通过,再使用 MethodMatcher 校验 类中所有的方法,只要有一个方法匹配上,代表该Advisor符合条件。

在这里宁可多通过,也不要校验太严格,因为在代理类中具体方法执行的时候,还会再一次使用Pointcut进行校验。所以该方法中会获取目标类型的所有接口,判断接口中的方法,有一个符合也会返回true

当获取到目标类型上的所有Advisor后,还需要对Advisor进行排序。Advisor的顺序决定了通知方法的应用顺序。

Advisor的排序主要分为两种

接下来看下spring是怎么实现排序的

AbstractAdvisorAutoProxyCreatorsortAdvisors提供了基于Ordered的排序,由spring的AnnotationAwareOrderComparator统一处理Ordered实现类或者添加@Ordered注解类的排序

AspectJAwareAdvisorAutoProxyCreator覆写了父类的sortAdvisors方法,在基于Ordered排序基础上提供了同一切面下不同通知之间的排序,具体排序实现委托给了PartialOrder

至此完成Advisor的查找、筛选、排序。

以上就是关于Spring AOP之AopProxy代理对象全部的内容,包括:Spring AOP之AopProxy代理对象、spring-AOP(二) 自动代理、等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/9473357.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-28
下一篇2023-04-28

发表评论

登录后才能评论

评论列表(0条)

    保存