前提回顾
前一篇文章主要介绍了 spring 核心特性机制的 IOC 容器机制和核心运作原理,接下来我们去介绍另外一个较为核心的功能,那就是 AOP 容器机制,主要负责承接前一篇代理模式机制中动态代理:JDKProxy 和 CglibProxy 的功能机制之后,我们开始研究一下如何实现一下相关的 AOP 容器代理机制的。
AOP 入口机制
如何实现将 Aspectj 的动态 weave 织入到 Spring 容器的 Bean 中?
实现的基本实现原理就是后置处理器:BeanPostProcessor 机制,实现动态化植入机制。
如何实现相关的 Aspectj 的 weave 织入时机
bean 在初始化的时候会进行调用对应的 BeanPostProcessor 的对应的方法会进行织入。
判断的基本流程
主要取决于 wrapIfNecessary 方法:
判断当前的 Bean 是 AOP 的基础设施类型
如果是基础设施类型,则直接回进行返回该 bean 对象,不会进行相关的初始化对应的 aspectj 的动态织入机制。
如果属于定制化的 bean 对象类型
会进行寻找相关的 Bean 对应的何时的加强通知类。
如果对应该对象的通知增强数组集合不为空
则会对该 bean 对象,额外进行增强操作生成相关的代理对象,并返回该执行之后的对象,否则会直接返回该对象即可。
筛选何时的通知器
getAdvicesAndAdvisorsForBean 方法是我们筛选 Advice 增强类的核心方法,主要用于过滤和筛选对应该 bean 的何时的增强器数组信息。
查找对应 Bean 的通知增强器
主要用于调用 AnnotationAwareAspectJAutoProxyCreator 的**findCandidateAdvisors()**方法,其内部会进行先关的核心构建相关的 Aspectj 的类的相关实现操作
构建先关 Aspectj 类 buildAspectJAdvisors 方法
-
首先先进行获取先关的所有容器的 BeanName 数据集合
-
在根绝上面的 BeanName 名称集合获取相关的 BeanType 类型集合
-
根据 BeanType 判断当前的 Bean 是否属于一个 Aspectj 的注解.类,如果不是则类不做任何处理。
构建实际的相关的 Advisors 类机制
advisorsFactory.getAdvisors 获取通知器
切点处理
切点类处理操作到此为止,还不完整接下来才是构建动态代理对象的真正执行操作,
-
获取上面操作中获取到的 Aspectj 类中的除了 PointCut 注解修饰的其他的方法列表。
-
根据对应的 Aspectj 类和相关的 Advisors 方法列表,创建相关的 Advisor 实现类,其中内部会进行遍历相关上一步的方法列表,并且调用对应的方法 method 对应的 getAdvisor 方法,建立 Advisor 对象。
-
创建相关的 AspectJExpressionPointCut 对象,并且从方法里的注解表达式进行解析,这最后设置到对应的门面层的 Advisor 对象实例。
-
实际的 Advisor 对象实现类对象的实际:InstantitationModelAwarePoincutAdvisorImpl 实例,并且调用其内部的 instantiateAdvice 方法构建通知机制。
-
其内部仍然会调用 getAdvice 方法,并且构建相关的注解的类型创建相应的通知。
筛选何时的通知器并且执行应用
findAdvisorsThatCanApply 方法
扩展相关的筛选出的通知器列表,extendAdvisors 方法,通知器列表首部添加一个 DefaultPointcutAdivosr 类型的通知器,也就是 ExposeInvocationInterceptor.ADVISOR 的实现机制。
创建代理对象
-
jdk 动态代理
-
cglib 动态代理
proxy-target-class
proxy-target-class 的属性值,代表是否可以支持代理实现类,默认采用的 false 代表着,当 bean 有实现接口的时候,会直接采用 jdk 的动态代理机制生成代理对象,如果是 true,则代表着使用 cglib 进行生成代理对象。
例如:
<aop:aspectj-autoproxy proxy-target-class = "true" /></aop>
复制代码
AopProxy 接口
-
CglibAopProxy 接口实现
-
JdkDynamicAopProxy 接口实现
AOP 代理对象调用同类的方法问题解决方案
expose-proxy 作用
前提是必须要配置相关的 expose-proxy 属性配置值为 true,才会进行暴露对应的代理机制。
为了解决目标方法调用同对象中的其他方法,其他方法的切面逻辑是无法实现,因为会涉及到相关的 this 操作而不是 proxy 对象机制。
可以实现使用 AopContext.currentProxy()强制转换为当前的代理对象。
拦截器链路执行
intercept 方法机制
获取相关的对应方法的拦截器栈链路,如果没有获取到相关的缓存链路,则会直接调用相关的 getInterceptorsAndDynamicInterceptorAdvice 获取先关的拦截器链。
方法拦截器相关的拦截操作连接点
会进行先关的 PointcutAdvisor 类型通知器,这里会调用相关的通知器所持有的切点(Pointcut)对类和方法进行匹配,匹配冲过这说明相关的向当前的方法进行织入逻辑控制。此外还会通过 geIntercptors()方法对非 MethodIntercptor 类型的通知进行转换。返回相关的拦截器数组,并且随后存入缓存中。
执行目标方法的方式
如果拦截器为空
则会直接通过代理机制的反射控制进行调用执行即可。
如果不为空
则例如 jdkDynamicAutoProxy 对象进行调用构建 ReflectiveMethodInvocation 对象,例如它的 process 方法启动拦截器栈的 invoke 方法。
-
invoke:执行拦截器栈
-
invokeJoinpoin():执行目标方法
处理返回值,并且返回该值。