了解springboot aop的动态 *** 方式有哪些种类?
有3种,前提均开启spring.aop.auto=true:
1. jdk动态 *** :当spring.aop.proxy-target-class=false, 引入了aspectjweaver依赖时生效
2. cglib *** :当spring.aop.proxy-target-class=true, 引入了aspectjweaver依赖时生效
3. 基础 *** :当spring.aop.proxy-target-class=true, 若没有aspectjweaver依赖时生效,只作用于框架内部的advisors,
我们既然用springboot那么就采用springboot的AopAutoConfiguration自动配置类来加载aop机制的,内部对@EnableAspectJAutoProxy进行了封装,扩展了一些配置项,同时还提供了ClassProxyingConfiguration配置(下面会讲到).
这个自动装配类会是spring boot框架自动会装配的,所以说默认aop机制是打开的,可以通过配置项:spring.aop.auto=false 手工关闭。
这个配置类会根据spring.aop.proxy-target-class配置项来决定采用jdk动态 *** 或者cglib动态 *** :
注意:AspectJAutoProxyingConfiguration配置类生效前提是@ConditionalOnClass(Advice.class),说明只有当引入了依赖项才生效:
而这里推荐使用spring-boot-starter-aop来传递依赖:
这里我们已经看到提供了原生spring的两种 *** 方式,接着看AopAutoConfiguration源码发现还有个ClassProxyingConfiguration配置类,其生效条件之一是@ConditionalOnMissingClass("org.aspectj.weaver.Advice"),就是当项目里没有aspectjweaver的依赖的时候生效。
我们进入AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry) *** ,通过几步调用跳转:
发现会去注册InfrastructureAdvisorAutoProxyCreator后置处理器,查看源码注释:
表明了InfrastructureAdvisorAutoProxyCreator只为基础的advisor做动态 *** ,而忽略应用定义的Advisors,说明项目中我们自定义的切面是不会被AOP *** 的。
前一篇文章主要介绍了 spring 核心特性机制的 IOC 容器机制和核心运作原理,接下来我们去介绍另外一个较为核心的功能,那就是 AOP 容器机制,主要负责承接前一篇 *** 模式机制中动态 *** :JDKProxy 和 CglibProxy 的功能机制之后,我们开始研究一下如何实现一下相关的 AOP 容器 *** 机制的。
实现的基本实现原理就是后置处理器:BeanPostProcessor 机制,实现动态化植入机制。
bean 在初始化的时候会进行调用对应的 BeanPostProcessor 的对应的 *** 会进行织入。
主要取决于 wrapIfNecessary *** :
如果是基础设施类型,则直接回进行返回该 bean 对象,不会进行相关的初始化对应的 aspectj 的动态织入机制。
会进行寻找相关的 Bean 对应的何时的加强通知类。
则会对该 bean 对象,额外进行增强操作生成相关的 *** 对象,并返回该执行之后的对象,否则会直接返回该对象即可。
getAdvicesAndAdvisorsForBean *** 是我们筛选 Advice 增强类的核心 *** ,主要用于过滤和筛选对应该 bean 的何时的增强器数组信息。
主要用于调用 AnnotationAwareAspectJAutoProxyCreator 的**findCandidateAdvisors()** *** ,其内部会进行先关的核心构建相关的 Aspectj 的类的相关实现操作
advisorsFactory.getAdvisors 获取通知器
切点类处理操作到此为止,还不完整接下来才是构建动态 *** 对象的真正执行操作,
扩展相关的筛选出的通知器列表,extendAdvisors *** ,通知器列表首部添加一个 DefaultPointcutAposr 类型的通知器,也就是 ExposeInvocationInterceptor.ADVISOR 的实现机制。
proxy-target-class 的属性值,代表是否可以支持 *** 实现类,默认采用的 false 代表着,当 bean 有实现接口的时候,会直接采用 jdk 的动态 *** 机制生成 *** 对象,如果是 true,则代表着使用 cglib 进行生成 *** 对象。
复制代码
前提是必须要配置相关的 expose-proxy 属性配置值为 true,才会进行暴露对应的 *** 机制。
为了解决目标 *** 调用同对象中的其他 *** ,其他 *** 的切面逻辑是无法实现,因为会涉及到相关的 this 操作而不是 proxy 对象机制。
可以实现使用 AopContext.currentProxy()强制转换为当前的 *** 对象。
获取相关的对应 *** 的拦截器栈链路,如果没有获取到相关的缓存链路,则会直接调用相关的 getInterceptorsAndDynamicInterceptorAdvice 获取先关的拦截器链。
会进行先关的 PointcutAdvisor 类型通知器,这里会调用相关的通知器所持有的切点(Pointcut)对类和 *** 进行匹配,匹配冲过这说明相关的向当前的 *** 进行织入逻辑控制。此外还会通过 geIntercptors() *** 对非 MethodIntercptor 类型的通知进行转换。返回相关的拦截器数组,并且随后存入缓存中。
则会直接通过 *** 机制的反射控制进行调用执行即可。
则例如 jdkDynamicAutoProxy 对象进行调用构建 ReflectiveMethodInvocation 对象,例如它的 process *** 启动拦截器栈的 invoke *** 。
处理返回值,并且返回该值。
原理:sping aop是可以通过预编译方式和运行期动态 *** 实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。AOP设计模式孜孜不倦追求的是调用者和被调用者之间的解耦,AOP 可以说也是这种目标的一种实现。
其原理的相关技术:
AOP是OOP的延续,是Aspect Oriented Programming的缩写,意思是面向切面编程。AOP(这里的AOP指的是面向切面编程思想,而不是Spring AOP)主要的的实现技术主要有Spring AOP和AspectJ。
AspectJ的底层技术是静态 *** ,即用一种AspectJ支持的特定语言编写切面,通过一个命令来编译,生成一个新的 *** 类,该 *** 类增强了业务类,这是在编译时增强,相对于下面说的运行时增强,编译时增强的性能更好。
Spring AOP采用的是动态 *** ,在运行期间对业务 *** 进行增强,所以不会生成新类,对于动态 *** 技术,Spring AOP提供了对JDK动态 *** 的支持以及CGLib的支持。
JDK动态 *** 只能为接口创建动态 *** 实例,而不能对类创建动态 *** 。需要获得被目标类的接口信息(应用Java的反射技术),生成一个实现了 *** 接口的动态 *** 类(字节码),再通过反射机制获得动态 *** 类的构造函数,利用构造函数生成动态 *** 类的实例对象,在调用具体 *** 前调用invokeHandler *** 来处理。