Spring Aop(十四)——Aop自动创建代理对象的原理

简介: Aop自动创建代理对象的原理 我们在使用Spring Aop时,通常Spring会自动为我们创建目标bean的代理对象,以使用对应的Advisor。前提是我们在使用Spring Aop时是使用的或,这是因为当我们在applicationContext.xml文件中通过的形式定义需要使用Aop的场景时,Spring会自动为我们添加AspectjAwareAdvisorAutoProxyCreator类型的bean;而我们定义了时,Spring会默认为我们添加AnnotationAwareAspectjAutoProxyCreator类型的bean。

Aop自动创建代理对象的原理

我们在使用Spring Aop时,通常Spring会自动为我们创建目标bean的代理对象,以使用对应的Advisor。前提是我们在使用Spring Aop时是使用的<aop:config/><aop:aspectj-autoproxy/>,这是因为当我们在applicationContext.xml文件中通过<aop:config/>的形式定义需要使用Aop的场景时,Spring会自动为我们添加AspectjAwareAdvisorAutoProxyCreator类型的bean;而我们定义了<aop:aspectj-autoproxy/>时,Spring会默认为我们添加AnnotationAwareAspectjAutoProxyCreator类型的bean。Spring中在bean实例化后能够对bean对象进行包装的是BeanPostProcessorAspectjAwareAdvisorAutoProxyCreatorAnnotationAwareAspectjAutoProxyCreator都是实现了BeanPostProcessor接口的。AnnotationAwareAspectjAutoProxyCreator的父类是AspectjAwareAdvisorAutoProxyCreator,而AspectjAwareAdvisorAutoProxyCreator的父类是AbstractAdvisorAutoProxyCreatorAbstractAdvisorAutoProxyCreator的父类是实现了BeanPostProcessor接口的AbstractAutoProxyCreator。它们的核心逻辑都是在bean初始化后找出bean容器中所有的能够匹配当前bean的Advisor,找到了则将找到的Advisor通过ProxyFactory创建该bean的代理对象返回。AspectjAwareAdvisorAutoProxyCreator在寻找候选的Advisor时会找到bean容器中所有的实现了Advisor接口的bean,而AnnotationAwareAspectjAutoProxyCreator则在AspectjAwareAdvisorAutoProxyCreator的基础上增加了对标注了@Aspect的bean的处理,会附加上通过@Aspect标注的bean中隐式定义的Advisor。所以这也是为什么我们在使用@Aspect标注形式的Spring Aop时需要在applicationContext.xml文件中添加<aop:aspectj-autoproxy/>。既然AspectjAwareAdvisorAutoProxyCreatorAnnotationAwareAspectjAutoProxyCreator都会自动扫描bean容器中的Advisor,所以当我们使用了<aop:config/><aop:aspectj-autoproxy/>形式的Aop定义时,如果因为某些原因光通过配置满足不了你Aop的需求,而需要自己实现Advisor接口时(一般是实现PointcutAdvisor接口),那这时候你只需要把自己的Advisor实现类,定义为Spring的一个bean即可。如果你在applicationContext.xml中没有定义<aop:config/><aop:aspectj-autoproxy/>,那你也可以直接在applicationContext.xml中直接定义AspectjAwareAdvisorAutoProxyCreatorAnnotationAwareAspectjAutoProxyCreator类型的bean,效果也是一样的。其实为了能够在创建目标bean的时候能够自动创建基于我们自定义的Advisor实现类的代理对象,我们的bean容器中只要有AbstractAutoProxyCreator类型的bean定义即可,当然了你实现自己的BeanPostProcessor,在其postProcessAfterInitialization方法中创建自己的代理对象也是可以的。但是本着不重复发明轮子的原则,我们尽量使用官方已经提供好的实现即可。AbstractAutoProxyCreator是继承自ProxyConfig的,所以我们在定义AbstractAutoProxyCreator子类的bean时,我们也可以手动的定义一些ProxyConfig中包含的属性,比如proxyTargetClassexposeProxy等。AbstractAutoProxyCreator的子类除了AspectjAwareAdvisorAutoProxyCreatorAnnotationAwareAspectjAutoProxyCreator外,我们可用的还有BeanNameAutoProxyCreatorDefaultAdvisorAutoProxyCreator

BeanNameAutoProxyCreator

BeanNameAutoProxyCreator可以用来定义哪些bean可与哪些Advisor/Advice绑定,以生成对应的代理对象。需要绑定的bean是通过beanNames属性来指定的,对应的是bean的名称,其中可以包含“*”号,表示任意字符,比如“abc*”则匹配任意名称以“abc”开始的bean;需要绑定的Advisor/Advice是通过interceptorNames来指定的,如果指定的是Advisor,那么是否可生成基于该Advisor的代理需要对应的bean能够匹配对应AdvisorPointcutAdvisor类型)的Pointcut;如果指定的是Advice,则该Advice会被包含在Pointcut恒匹配的Advisor中,即能够与所有的bean绑定生成对应的代理,且会对所有的方法调用起作用。 指定interceptorNames时是不能使用通配符的,只能精确的指定需要应用的Advisor/Advice对应的bean名称。

<bean id="userService" class="com.elim.learn.spring.aop.service.UserServiceImpl"/>
<bean id="myService" class="com.elim.learn.spring.aop.service.MyService"/>
	
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
	<!-- 匹配userService和所有名称以my开头的bean -->
	<property name="beanNames" value="userService, my*"/>
	<!-- interceptorNames中不能使用通配符,只能是精确匹配,
             即精确指定Advisor/Advice的bean名称 -->
	<property name="interceptorNames" value="logBeforeAdvice, myAdvisor "/>
</bean>
	
<bean id="logBeforeAdvice" 
    class="com.elim.learn.spring.aop.advice.LogBeforeAdvice" />
	 
<bean id="myAdvisor" class="com.elim.learn.spring.aop.advisor.MyAdvisor"/>

如上就是一个使用BeanNameAutoProxyCreator建立指定的bean基于指定的Advisor/Advice的代理对象的示例。示例中我们指定interceptorNames时特意应用了一个Advisor实现和一个Advice实现。Advice会应用于所有绑定的bean的所有方法调用,而Advisor只会应用于其中的Pointcut能够匹配的方法调用。这里的源码我就不提供了,有兴趣的朋友可以自己试试。

DefaultAdvisorAutoProxyCreator

DefaultAdvisorAutoProxyCreator的父类也是AbstractAdvisorAutoProxyCreatorDefaultAdvisorAutoProxyCreator的作用是会默认将bean容器中所有的Advisor都取到,如果有能够匹配某一个bean的Advisor存在,则会基于能够匹配该bean的所有Advisor创建对应的代理对象。需要注意的是DefaultAdvisorAutoProxyCreator在创建bean的代理对象时是不会考虑Advice的,只是Advisor。如上面的示例中,如果我们希望所有的bean都能够自动的与匹配的Advisor进行绑定生成对应的代理对象,那么我们可以调整配置如下。

<bean id="userService" class="com.elim.learn.spring.aop.service.UserServiceImpl"/>
<bean id="myService" class="com.elim.learn.spring.aop.service.MyService"/>
	
<bean 
 class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
	
<bean id="myAdvisor" class="com.elim.learn.spring.aop.advisor.MyAdvisor"/>

使用DefaultAdvisorAutoProxyCreator时可能我们并不希望为所有的bean定义都自动应用bean容器中的所有Advisor,而只是希望自动创建基于部分Advisor的代理对象。这个时候如果我们期望应用自动代理的Advisor的bean定义的名称都是拥有固定的前缀时,则我们可以应用DefaultAdvisorAutoProxyCreatorsetAdvisorBeanNamePrefix(String)指定需要应用的Advisor的bean名称的前缀,同时需要通过setUsePrefix(boolean)指定需要应用这种前缀匹配机制。如我们的bean容器中有两个Advisor定义,一个bean名称是“myAdvisor”,一个bean名称是“youAdvisor”,如果只期望自动创建基于bean名称以“my”开始的Advisor的代理,则可以进行如下配置。

<bean 
  class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
	<property name="usePrefix" value="true" />
	<!-- 匹配所有bean名称以my开始的Advisor -->
	<property name="advisorBeanNamePrefix" value="my" />
</bean>

(注:本文是基于Spring4.1.0所写,Elim写于2017年5月12日)

目录
相关文章
|
2月前
|
XML 安全 Java
使用 Spring 的 @Aspect 和 @Pointcut 注解简化面向方面的编程 (AOP)
面向方面编程(AOP)通过分离横切关注点,如日志、安全和事务,提升代码模块化与可维护性。Spring 提供了对 AOP 的强大支持,核心注解 `@Aspect` 和 `@Pointcut` 使得定义切面与切入点变得简洁直观。`@Aspect` 标记切面类,集中处理通用逻辑;`@Pointcut` 则通过表达式定义通知的应用位置,提高代码可读性与复用性。二者结合,使开发者能清晰划分业务逻辑与辅助功能,简化维护并提升系统灵活性。Spring AOP 借助代理机制实现运行时织入,与 Spring 容器无缝集成,支持依赖注入与声明式配置,是构建清晰、高内聚应用的理想选择。
364 0
|
25天前
|
XML Java 数据格式
《深入理解Spring》:AOP面向切面编程深度解析
Spring AOP通过代理模式实现面向切面编程,将日志、事务等横切关注点与业务逻辑分离。支持注解、XML和编程式配置,提供五种通知类型及丰富切点表达式,助力构建高内聚、低耦合的可维护系统。
|
3月前
|
人工智能 监控 安全
Spring AOP切面编程颠覆传统!3大核心注解+5种通知类型,让业务代码纯净如初
本文介绍了AOP(面向切面编程)的基本概念、优势及其在Spring Boot中的使用。AOP作为OOP的补充,通过将横切关注点(如日志、安全、事务等)与业务逻辑分离,实现代码解耦,提升模块化程度、可维护性和灵活性。文章详细讲解了Spring AOP的核心概念,包括切面、切点、通知等,并提供了在Spring Boot中实现AOP的具体步骤和代码示例。此外,还列举了AOP在日志记录、性能监控、事务管理和安全控制等场景中的实际应用。通过本文,开发者可以快速掌握AOP编程思想及其实践技巧。
|
3月前
|
人工智能 监控 安全
如何快速上手【Spring AOP】?核心应用实战(上篇)
哈喽大家好吖~欢迎来到Spring AOP系列教程的上篇 - 应用篇。在本篇,我们将专注于Spring AOP的实际应用,通过具体的代码示例和场景分析,帮助大家掌握AOP的使用方法和技巧。而在后续的下篇中,我们将深入探讨Spring AOP的实现原理和底层机制。 AOP(Aspect-Oriented Programming,面向切面编程)是Spring框架中的核心特性之一,它能够帮助我们解决横切关注点(如日志记录、性能统计、安全控制、事务管理等)的问题,提高代码的模块化程度和复用性。
|
3月前
|
设计模式 Java 开发者
如何快速上手【Spring AOP】?从动态代理到源码剖析(下篇)
Spring AOP的实现本质上依赖于代理模式这一经典设计模式。代理模式通过引入代理对象作为目标对象的中间层,实现了对目标对象访问的控制与增强,其核心价值在于解耦核心业务逻辑与横切关注点。在框架设计中,这种模式广泛用于实现功能扩展(如远程调用、延迟加载)、行为拦截(如权限校验、异常处理)等场景,为系统提供了更高的灵活性和可维护性。
|
安全 Java Spring
Spring之Aop的底层原理
Spring之Aop的底层原理
|
Java Spring 容器
【Spring AOP底层实现原理】
【Spring AOP底层实现原理】
398 0
|
设计模式 Java uml
Spring AOP 原理
Spring AOP 原理
111 0
Spring5入门到实战------9、AOP基本概念、底层原理、JDK动态代理实现
这篇文章是Spring5框架的实战教程,深入讲解了AOP的基本概念、如何利用动态代理实现AOP,特别是通过JDK动态代理机制在不修改源代码的情况下为业务逻辑添加新功能,降低代码耦合度,并通过具体代码示例演示了JDK动态代理的实现过程。
Spring5入门到实战------9、AOP基本概念、底层原理、JDK动态代理实现
|
12月前
|
Java 开发者 Spring
Spring AOP 底层原理技术分享
Spring AOP(面向切面编程)是Spring框架中一个强大的功能,它允许开发者在不修改业务逻辑代码的情况下,增加额外的功能,如日志记录、事务管理等。本文将深入探讨Spring AOP的底层原理,包括其核心概念、实现方式以及如何与Spring框架协同工作。