`
herman_liu76
  • 浏览: 99947 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

springboot的aop自动代理实现分析笔记

阅读更多
# 目的
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-黑马程序员学习笔记

    在Spring中,AOP通过代理模式实现,分为JDK动态代理和CGLIB代理。 1. **切面(Aspect)**:定义了关注点的模块化,包含通知(Advice)和切点(Pointcut)。 2. **通知(Advice)**:在特定连接点执行的代码,如前置...

    Spring整合Mybatis与SpringBoot整合Mybatis原理分析

    - **Spring的IoC和AOP**: 了解Spring如何通过依赖注入和面向切面编程实现组件间的解耦。 - **Mybatis的映射机制**: 明白Mapper接口和XML映射文件是如何协同工作的。 - **事务管理策略**: 学习Spring的事务管理...

    springboot各种使用与源码笔记

    SpringBoot是Spring框架的一种简化和快速开发方式,它...在阅读提供的源码笔记时,应重点关注SpringBoot的启动流程、自动配置机制以及如何集成和配置各种服务。同时,理解并运用最佳实践,能够提升代码质量和应用性能。

    SpringBoot笔记.md

    - 基于动态代理机制实现。对于接口,使用JDK动态代理;对于非接口,则使用CGLIB库进行字节码增强。 ##### 2.4 XML配置IOC实例演示 下面通过具体的步骤来展示如何使用XML配置文件来实现Spring的IOC容器管理。 1. ...

    springboot学习源码.rar(0积分下载)

    在SpringBoot的学习过程中,源码分析是非常重要的环节。通过阅读源码,我们可以深入理解其内部工作原理,提高我们的编程技能和问题解决能力。"springboot学习源码.rar"这个资源包含了SpringBoot的学习笔记和演习项目...

    Java笔记,从基础到进阶到源码分析,包括但不限于SSM,SpringBoot,SpringCloud,中间件.zip

    这份名为“Java笔记,从基础到进阶到源码分析,包括但不限于SSM,SpringBoot,SpringCloud,中间件”的压缩包文件,显然是一个全面学习Java技术体系的宝贵资源。我们将详细探讨其中涵盖的关键知识点。 首先,基础...

    spring5源码分析笔记

    Spring5源码分析笔记旨在深入理解Spring的工作原理,帮助开发者提升技能,优化代码,以及更好地利用其核心特性。以下是对Spring5源码的一些关键知识点的详细解释: 1. **依赖注入(Dependency Injection,DI)**:...

    Spring 学习笔记六

    AOP基于代理模式实现,Spring提供了多种类型的代理,包括JDK动态代理和CGLIB代理。开发者可以定义切面(Aspect),包含切入点表达式(Pointcut)和通知(Advice)。通过`@Aspect`、`@Before`、`@After`等注解,可以...

    springboot全局配置文件

    - `spring.aop.auto`: 是否自动开启AspectJ的代理功能,默认为`true`。 - `spring.aop.proxy-target-class`: 是否创建基于子类的CGLIB代理,默认为`false`,即使用标准Java接口代理。 ##### 3. 应用身份配置...

    Spring学习笔记(内含代码)

    Spring还支持AOP代理,可以为特定的对象创建动态代理,实现如日志、性能监控等切面功能。此外,Spring集成了许多其他框架和库,如Quartz定时任务、Email服务、缓存支持(如 Ehcache 和 Redis)以及消息中间件(如 ...

    spring学习笔记,包括源码学习

    例如,你会学习到Spring如何通过反射和CGLIB动态代理来实现依赖注入,以及BeanFactory和ApplicationContext这两个容器的区别。你可能还会探索Spring的事件发布机制、AOP的实现方式,以及Spring如何处理事务。 在...

    Spring&Mybatis&SpringMVC总结笔记-最全最基础.pdf

    IoC(控制反转)和DI(依赖注入)是Spring的核心概念,它们通过反转控制(将对象的创建和管理交给容器进行)来实现依赖关系的自动注入。AOP(面向切面编程)允许开发者定义方法执行前后及抛出异常后的特定逻辑,它...

    spring培训第二天

    Spring AOP通过代理模式实现,支持方法前、后、异常处理等多种通知类型。 4. **Spring Bean的生命周期**: Spring中的Bean有其特定的生命周期,包括实例化、初始化、配置、正常服务以及销毁。开发者可以通过实现...

    学习笔记::books:JAVA,Spring,SpringMVC,SpringBoot,Mybatis,Vue,MySQL,MongoDB,Radis,Docker,Nginx,......笔记

    这些学习笔记涵盖了IT领域的多个重要方面,包括编程语言、框架、数据库、缓存技术、容器化和Web服务器等。下面将分别对这些知识点进行详细解释。 1. **Java**: Java是一种广泛使用的面向对象的编程语言,以其跨平台...

    Spring笔记1

    Spring 框架还支持面向切面编程(AOP),允许开发者在不修改业务代码的情况下,实现横切关注点,如日志、事务管理和安全控制。 在Spring中,事务管理是一项重要功能,它提供了声明式和编程式的事务处理方式,使得...

    study-spring:春天学习项目笔记

    2. **AOP(Aspect-Oriented Programming,面向切面编程)**:Spring提供了基于代理的AOP实现,允许我们在不修改源代码的情况下,插入跨切面的关注点,如日志、事务管理等。 3. **数据访问/集成**:Spring支持多种...

    java后端面试题(按天复习).zip

    - **SpringBoot**:自动配置、起步依赖、Spring Boot Actuator等。 6. **数据库** - **SQL语句**:查询优化、索引、事务处理。 - **JDBC**:连接池(C3P0、Druid、HikariCP)、批处理。 - **NoSQL**:MongoDB、...

Global site tag (gtag.js) - Google Analytics