到目前为止,我们已经考虑了通过使用 ProxyFactoryBean 或类似的工厂 Bean 显式创建 AOP 代理。
Spring 还让我们使用 「自动代理」的 Bean 定义,它可以自动代理选定的 Bean 定义。这是建立在 Spring 的 「Bean Post Processor」基础设施上的,它可以在容器加载时修改任何 Bean 定义。
在这种模式下,你在你的 XML Bean 定义文件中设置了一些特殊的 Bean 定义来配置自动代理基础设施。这让你可以声明符合自动代理的目标。你不需要使用 ProxyFactoryBean。
有两种方法可以做到这一点:
- 通过使用一个自动代理创建者,在当前上下文中引用特定的 bean。
- 值得单独考虑的自动代理创建的一个特殊情况:由源级元数据属性驱动的自动代理创建。
Auto-proxy Bean Definitions
本节涉及 org.springframework.aop.framework.autoproxy
包提供的自动代理创建者。
BeanNameAutoProxyCreator
BeanNameAutoProxyCreator 类是一个 BeanPostProcessor,它为名称与字面值或通配符相匹配的 Bean 自动创建 AOP 代理。下面的例子展示了如何创建一个 BeanNameAutoProxyCreator Bean。
<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 属性,而不是一个 interceptors 的列表,以允许多例顾问的正确行为。被命名的 「拦截器」可以是顾问或任何 advice 类型。
与一般的自动代理一样,使用 BeanNameAutoProxyCreator 的主要意义在于将相同的配置一致地应用于多个对象,而配置量最小。它是将声明性事务应用于多个对象的一个流行选择。
名字匹配的 Bean 定义,比如前面例子中的 jdkMyBean 和 onlyJdk ,都是目标类的普通 Bean 定义。一个 AOP 代理是由BeanNameAutoProxyCreator 自动创建的。同样的 advice 被应用于所有匹配的 Bean。请注意,如果使用顾问(而不是前面例子中的拦截器),那么对不同的 Bean 适用的 pointcuts 可能不同。
DefaultAdvisorAutoProxyCreator
一个更普遍和极其强大的自动代理创建者是 DefaultAdvisorAutoProxyCreator。它可以自动应用当前上下文中符合条件的顾问,而不需要在自动代理顾问的 Bean 定义中包含特定的 Bean 名称。它提供了与 BeanNameAutoProxyCreator 一样的一致配置和避免重复的优点。
使用这一机制涉及到:
- 指定一个 DefaultAdvisorAutoProxyCreator bean 定义。
- 在相同或相关的背景下指定任何数量的顾问。注意,这些必须是顾问,而不是拦截器或其他 advice 。这是必要的,因为必须有一个评估的 pointcut,以检查每个 advice 对候选 bean 定义的资格。
DefaultAdvisorAutoProxyCreator 会自动评估每个顾问中包含的 pointcut,以查看它应该对每个业务对象(例如例子中的 businessObject1 和businessObject2)应用什么(如果有的话)advice。
这意味着任何数量的顾问可以被自动应用到每个业务对象。如果任何顾问中的任何点都不匹配业务对象中的任何方法,那么该对象就不会被代理。当 Bean 定义被添加到新的业务对象时,如果有必要,它们会被自动代理。
一般来说,自动代理的优点是使调用者或依赖者不可能获得一个不被 advice 的对象。在这个 ApplicationContext 上调用 getBean("businessObject1")
会返回一个 AOP 代理,而不是目标业务对象。(前面显示的 「内部 Bean」 语义也提供了这个好处)。
下面的例子创建了一个 DefaultAdvisorAutoProxyCreator Bean 和本节讨论的其他元素:
<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 就非常有用。一旦基础设施定义到位,你可以添加新的业务对象而不包括具体的代理配置。你也可以轻松地加入额外的切面(例如,跟踪或性能监控方面),只需对配置做最小的改变。
DefaultAdvisorAutoProxyCreator 提供了对过滤(通过使用命名惯例,以便只对某些顾问进行评估,这允许在同一工厂中使用多个不同配置的 AdvisorAutoProxyCreator)和排序的支持。顾问可以实现 org.springframework.core.Ordered
接口,以确保正确的排序,如果这是一个问题。前面例子中使用的 TransactionAttributeSourceAdvisor 有一个可配置的顺序值。默认设置是无序的。