对于最新稳定版本,请使用 Spring Framework 7.0.6spring-doc.cadn.net.cn

使用“自动代理”功能

到目前为止,我们已经讨论了通过使用 ProxyFactoryBean 或类似的工厂 bean 来显式创建 AOP 代理。spring-doc.cadn.net.cn

Spring 还允许我们使用“自动代理”(auto-proxy)的 bean 定义,它可以自动为选定的 bean 定义创建代理。这是基于 Spring 的“bean 后处理器”(bean post processor)基础设施构建的,该机制可在容器加载时修改任意 bean 定义。spring-doc.cadn.net.cn

在此模型中,您在 XML bean 定义文件中设置一些特殊的 bean 定义,以配置自动代理基础设施。这使您可以声明符合自动代理条件的目标对象。您无需使用 ProxyFactoryBeanspring-doc.cadn.net.cn

有两种方法可以实现这一点:spring-doc.cadn.net.cn

  • 通过使用引用当前上下文中特定 bean 的自动代理创建器。spring-doc.cadn.net.cn

  • 一种特殊的自动代理创建情况,值得单独考虑:由源代码级别的元数据属性驱动的自动代理创建。spring-doc.cadn.net.cn

自动代理 Bean 定义

本节介绍 org.springframework.aop.framework.autoproxy 包所提供的自动代理创建器。spring-doc.cadn.net.cn

BeanNameAutoProxyCreator

BeanNameAutoProxyCreator 类是一个 BeanPostProcessor,它会自动为名称与字面值或通配符匹配的 bean 创建 AOP 代理。以下示例展示了如何创建一个 BeanNameAutoProxyCreator bean:spring-doc.cadn.net.cn

<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
	<property name="beanNames" value="jdk*,onlyJdk"/>
	<property name="interceptorNames">
		<list>
			<value>myInterceptor</value>
		</list>
	</property>
</bean>

ProxyFactoryBean 类似,这里提供的是 interceptorNames 属性,而不是一个拦截器列表,以便原型(prototype)通知器(advisor)能够表现出正确的行为。所命名的“拦截器”可以是通知器(advisor),也可以是任意类型的通知(advice)。spring-doc.cadn.net.cn

与一般的自动代理一样,使用 BeanNameAutoProxyCreator 的主要目的是以最少的配置量,将相同的配置一致地应用于多个对象。它常被用于对多个对象应用声明式事务。spring-doc.cadn.net.cn

名称匹配的 Bean 定义(例如前面示例中的 jdkMyBeanonlyJdk)是具有目标类的普通 Bean 定义。BeanNameAutoProxyCreator 会自动为它们创建 AOP 代理。相同的增强(advice)会被应用到所有匹配的 Bean 上。请注意,如果使用的是通知器(advisors)(而不是前面示例中的拦截器),那么切入点(pointcuts)可能会对不同的 Bean 产生不同的应用效果。spring-doc.cadn.net.cn

DefaultAdvisorAutoProxyCreator

一种更为通用且功能强大的自动代理创建器是 DefaultAdvisorAutoProxyCreator。它会自动将当前上下文中符合条件的增强器(advisor)应用到相应 bean 上,而无需在自动代理增强器的 bean 定义中显式指定具体的 bean 名称。它与 BeanNameAutoProxyCreator 一样,具有配置一致性并能避免重复的优点。spring-doc.cadn.net.cn

使用此机制包括:spring-doc.cadn.net.cn

  • 指定一个 DefaultAdvisorAutoProxyCreator 的 bean 定义。spring-doc.cadn.net.cn

  • 在同一上下文或相关上下文中指定任意数量的顾问(Advisor)。请注意,这些必须是顾问(Advisor),而不是拦截器(Interceptor)或其他类型的通知(Advice)。这是必要的,因为必须存在一个切入点(Pointcut)用于评估,以检查每条通知对候选 Bean 定义的适用性。spring-doc.cadn.net.cn

DefaultAdvisorAutoProxyCreator 会自动评估每个通知器(advisor)中包含的切入点(pointcut),以确定应将哪些(如果有的话)通知(advice)应用到每个业务对象上(例如示例中的 businessObject1businessObject2)。spring-doc.cadn.net.cn

这意味着任意数量的通知器(advisors)都可以自动应用于每个业务对象。如果这些通知器中的任何切入点(pointcut)都不匹配该业务对象中的任何方法,则该对象不会被代理。当为新的业务对象添加 Bean 定义时,如有必要,它们会自动被代理。spring-doc.cadn.net.cn

自动代理(Auto-proxying)通常具有一个优势,即调用者或依赖项无法获取未经增强(un-advised)的对象。在此getBean("businessObject1")上调用ApplicationContext返回的是一个AOP代理,而不是目标业务对象。(前面所示的“内部bean”(inner bean)语法也提供了这一优势。)spring-doc.cadn.net.cn

以下示例创建了一个 DefaultAdvisorAutoProxyCreator bean 以及本节中讨论的其他元素:spring-doc.cadn.net.cn

<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>

<bean class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor">
	<property name="transactionInterceptor" ref="transactionInterceptor"/>
</bean>

<bean id="customAdvisor" class="com.mycompany.MyAdvisor"/>

<bean id="businessObject1" class="com.mycompany.BusinessObject1">
	<!-- Properties omitted -->
</bean>

<bean id="businessObject2" class="com.mycompany.BusinessObject2"/>

如果你希望将相同的增强(advice)一致地应用到许多业务对象上,DefaultAdvisorAutoProxyCreator 非常有用。一旦基础设施的定义就位,你就可以添加新的业务对象,而无需包含特定的代理配置。你也可以轻松地加入额外的切面(例如,跟踪或性能监控切面),且只需对配置进行极少的修改。spring-doc.cadn.net.cn

DefaultAdvisorAutoProxyCreator 提供了过滤支持(通过使用命名约定,仅对特定的通知器(advisor)进行评估,从而允许在同一工厂中使用多个配置不同的 AdvisorAutoProxyCreator)以及排序功能。 如果排序是一个问题,通知器可以实现 org.springframework.core.Ordered 接口以确保正确的顺序。 前面示例中使用的 TransactionAttributeSourceAdvisor 具有一个可配置的 order 值,默认设置为无序。spring-doc.cadn.net.cn