# 目的
aop功能是spring的核心功能之一,本文分析一下作者的设计思路。
之前写过一些源码分析,发现写的太细,代码太多根本不方便记忆,所以这次简单的写一写,重点是思路。
# 一、先上结构图
这个图左上的核心类AnnotationAwareAspectJAutoProxyCreator是通过注解import进spring容器的一个后置处理bean,它有多层继承结构,有两个核心操作,分别进行了扩展说明。
# 二、springboot关于aop自动代理的实现
springboot的自动配置类-->AopAutoConfigurationt很简单,只是引入spring-framework的@EnableAspectJAutoProxy注解,将激活代理功能。重点是import一个BeanDefinitionRegistry,会比较灵活的注册你的bean到容器中。
# 三、@EnableAspectJAutoProxy注解
导入的后置处理器,它的方法postProcessBeforeInstantiation,是一个spring容器调用的方法。
spring容器比如放的是可以用的bean,类比人类是可以为社会工作的人。那么所有的人,在出生(Instantiation)前要有做产检的操作,出生后要喂养的操作,在上学(初始化init)前要学前教育,在上学后要进行招聘操作。Aspectj代理就是在出生前进行产检操作。
- postProcessBeforeInstantiation的核心语句有两句,下面分析:
## 1.【核心语句一】对所有的aspectj类进行处理。
- 方法getAdvicesAndAdvisorsForBean由子类完成。
- 子类中由**[a]找出所有的advisor** 与\ **
过滤合适的advisor**两部分组成。
[b]### 1.1 [a]找出所有的advisor
~~[a]工作由自己aware beanFactory操作时,自己所new的一个类处理的,把beanFactory给它。它也是从容器中找产生advisor的类。
new的这个类,是自己的内部类,局部工作专门它内部类做,如果需要什么资源找外部类要。但实际中找不到aspectj相关的内容,只是advisor.class的内容。~~ (这个方法会被子类覆盖,略过)
**[a]工作:当在aspectj情况时,实际上是在子类的子类,即最终的creator类中重写了一遍(super兼容上面方式的结果),可能是以前没考虑anotationAspectj的情况吧。同样new 了一个aspectJAdvisorsBuilder,让它来生成advisor。不同于父类中只传了beanFactory,这里还传了advisorFactory,也是New出来的一个类。等于是new 出了一个Factory,又new 了一个Builer,把Factory给Builer用。**
按说Builer就可以了,为何又弄一个advisorFactory,而且Factory里还有一个AspectInstanceFactory?builer中含有两个缓存,advisorsCache和facotryCache,可能是缓存作用的剥离吧。
ReflectiveAspectJAdvisorFactory是真正的advisorFactory;但aspectj方式要转成Advisor的,所以有两个层次的Factory。
为何不是上层builer自己new一个advisorFactory类呢?advisorFactory内部就New了AspectInstanceFactory。自己用的自己new呗,也许是advisorFactory可以由外部set进去,可修改,统一由外面设置进去。如同我找一个人A做工作,他可以找另一个人B做工作,但另一个人B的工作很重要,我还是自己找好了B介绍给A来用吧。
### 1.2 类关系特点:
工作让advisorbuilder做,它又让advisorFactory来做,但信息不是advisor格式的,是aspectj的,所以它又让更下一层的AspectInstanceFactory做一部分工作。这么设计层次明确,产生的类专注于其中重要的部分工作。
### 1.3 [b]过滤合适的advisor
-
工作也交给AopUtils来处理,参数是**上面的结果**与**当前正在后置处理容器中的bean**。可看出,这两个工作都安排其它类专门做。这个操作只是canApply判断一下,过滤一下,简单不表。
## 2.【核心语句二】用上面的处理结果,代理容器中符合条件的类,产生代理类。
[b]### 2.1 调用过程
- createProxy工作,由new ProxyFactory()来完成。这里用了一个我叫做老板模式的设计。(老板持有资源信息,对外提供功能调用,但具体工作交内部的类完成,同时把自己传给下级用来协助工作用的资源)
- ProxyFactory拥有copyFrom资源,advisors,targetSource等资源与属性,作为老板可以返回最终要的代理对象,是对外功能。
- 但老板内部是new 了一个AopProxy具体做事的,就是找了一个真正干活的DefaultAopProxyFactory来工作的,并把自己传给它,工作中要啥协助找老板我。
- DefaultAopProxyFactory作为具体干活的,它有两个手,比如android和IOS。看情况new出不同的手下来工作,还把老板传给它们调用,只告诉它们这是一个协助者。看来这个DefaultAopProxyFactory是中层领导。
- 最终干活的,比如是JdkDynamicAopProxy,它要完成代理对象的工作,就必须产生接口,有invokeHandler。它利用老板的advised信息得到接口,又利用这个信息产生调用链,给自己的invoke方法用。
- invoke时,把所有的调用参数信息(含调用链)包装成一个ReflectiveMethodInvocation,让它自己推进,给自己最终结果即可。
- ReflectiveMethodInvocation的推进就是从链中找一个调用者,把自己this传进去。调用者调用后,再返回this推进,再找下一个,再返回自己,再找下一个...真到自己指针记录链条走完了。
### 2.2 类关系设计特点:
老板持有参数,找一个人做,这个人按两个情况找下一级做,下一级用老板的参数真正工作。而它把老板的参数进行使用,产生了需要的东东,让外部的JDK底层来做了。分工合理。
另外想起在recketmq中,有老板有一个内部类被传递到层次功能类使用,功能类需要资源时找这个内部类,内部类天生关联老板。类似下派一个秘书。
# 四、主要的名词
简单理解记忆:
- advisor:包含一个切点pointcut与对应的advise的组合。aspectj类中的方法都生成一个个advisor。
- advise:可以认为是前置/后置/环绕方法方法拦截器。
- advised:advisors与一个接口的组合好。
- invocation:包含了调用所有的信息找包,可以让其自行preceed得到结果
- invoke:要外部传部分内容再invoke,比如method.invoke。
- inteceptor拦截时,处理的内容都是外面传来的。
- 调用链执行一般是:链条自己执行时选择其中一个节点执行同时把自己传进去,选中的节点执行后,再推动传来的链条再执行,环环相扣。当时链条执行完,就执行被代理对象的方法了。链条通常是protoType,而节点通常是单例。
# 五、备注
XML方式配置aop:
## 5.1 方法一:
<context:component-scan base-package="com.lzj"></context:component-scan>
<aop:config>
<!-- 配置切入点 expression填写切入点表达式 -->
<!-- 切记写上execution前缀 刚刚就没写 启动报错!
//execution (* *.*(..) ),这么写,就像 【返回值 类.方法(参数)】
// 第一个* 代表着 返回类型是任意的
// 第二个* 代表着 类的全限定名 * 代表着所有
// *(..) 代表着 任意方法 任意的参数
-->
<aop:pointcut expression="execution(* com.lzj.service.Impl..*.add(..))" id="pointcut"/>
<!-- 通知类:配置切面 切面是切入点和通知的结合 -->
<aop:aspect ref="myAdvise">
<!-- 指定名为beforeMethod方法,作为"前置"通知, -->
<aop:before method="beforeMethod" pointcut-ref="pointcut"/>
<aop:around method="around" pointcut-ref="pointcut"/>
<aop:after-returning method="afterReturn" pointcut-ref="pointcut"/>
<aop:after-throwing method="afterException" pointcut-ref="pointcut"/>
<aop:around method="around" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>
</beans>
<!--还发现配置如下,可以理解一下advisor/adviser-->
<!--还发现配置如下,可以理解一下advisor/adviser-->
<aop:aspect ref="helloAspect">
<!—以下使用了两种方法定义切入点 pointcut-ref和pointcut-->
<aop:before pointcut-ref="helloPointcut" method="beforeAdvice" />
<aop:after pointcut="execution(* com.lei.demo.aop.schema..*.*(..))" method="afterFinallyAdvice" />
</aop:aspect>
<!-- 配置切面
advisor:advice(public class HelloAroundAdvice implements MethodInterceptor)+ 切点定义。
在一个切点上,做什么拦截操作的组合,就是一个advisor。所以aspect类的一个前/后,就是一个advisor。
-->
<aop:config>
<aop:pointcut id="helloPointcut" expression="execution(* com.lei.demo.aop.schema..*.*(..))" /><!--advice-ref is a MethodInterceptor-->
<aop:advisor advice-ref="helloArroundAdvice" pointcut-ref="helloPointcut"/>
</aop:config>
## 5.2 方法二
<!--切面类上,写上切点,方法-->
<beans>
<context:component-scan base-package="com.lzj"></context:component-scan>
<!-- 3.开启使用注解完成织入 这一步非常重要-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
## 5.3 其它aop基础上的应用
再看其它aop基础上的应用就比较简单了,少不了后置处理器,相关的advior与advise的实现不同,都是方法拦截。
异步操作:ProxyAsyncConfiguration
- AsyncAnnotationBeanPostProcessor后置处理
- aware容器时,产生AsyncAnnotationAdvisor
- buildAdvice时,产生AnnotationAsyncExecutionInterceptor
- invoke(MethodInvocation)时,产生new Callable执行invocation.proceed()
缓存操作:ProxyCachingConfiguration
- advise:BeanFactoryCacheOperationSourceAdvisor
- Advice:CacheInterceptor
- invoke-->execute
事务操作:ProxyTransactionManagementConfiguration
- advise:BeanFactoryTransactionAttributeSourceAdvisor
- Advice:TransactionInterceptor
- invoke-->invokeWithinTransaction
分享到:
相关推荐
SpringBoot AOP各种注解、自定义注解、鉴权使用案例SpringBoot AOP各种注解、自定义注解、鉴权使用案例SpringBoot AOP各种注解、自定义注解、鉴权使用案例
SpringBoot AOP 写法一: @Before("execution(* com.bjpowernode.springboot07.javabean.Man.eat(..))") 一、AOP开发 1.1 概述 1.2使用方法 1.3创建项目并添加maven依赖 1.4 创建Javabean测试类 1.5 创建切面 1.6 ...
在Springboot上使用AOP的简单实例源码,可以结合本人的文章一起学习理解 https://blog.csdn.net/vincent_yuan89/article/details/85128009
只是简单集成了下一个aop的前置before小demo,自己做记录.
通过SpringAop实现多数据源的动态切换 并采用Druid连接池,可扩展继续增加数据库配置。
springBoot+mybatis+AOP实现读写分离,在代码层面直接实现,无需任何插件,简单易懂,非常适合作为解决数据库并发大的解决方案
springboot spring aop 拦截器 注解方式实现脱敏(涉及到:pom.xml -->application.properties --->启动类-->拦截器)
该项目运用SpringBoot框架,MyBatis持久层,SqlSession映射,AOP技术,对项目日志进行管理
高级软件人才培训专家-day13-SpringBoot AOP
Springboot整合AOP AOP概念:面向切面编程:扩展功能不修改源代码实现 AOP采用横向抽取机制,取代传统的纵向继承体系重复性代码(性能监视,事务管理,安全检查,缓存)
本篇文章主要介绍了SpringBoot AOP方式实现多数据源切换的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
源代码是spring-boot添加aop切面功能的demo,简单易懂.
SpringBoot+AOP+TraceID.pdf
AOP的意思就是面向切面编程。本文主要是通过梳理JDK中自带的反射机制,实现 AOP动态代理模式,这也是Spring AOP 的实现原理
在SpringBoot中演示实现了aop的使用方法,包括pointcut和Advice
spring boot AOP注解方式实现多数据源整合(从零开始搭建框架到配置多数据源实践小例子)
为了保证数据传输的安全性,跟其他系统进行数据交互时,双方应该约定好密钥,把数据进行加密,接口签名,这样双方调用接口时,验证接口签名一致时就表明数据传输过程中没有被修改。
主要介绍了SpringBoot使用AOP+注解实现简单的权限验证的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
主要介绍了Springboot通过aop实现事务控制过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
spring框架使用xml配置文件实现aop