使用“自动代理”设施

到目前为止,我们已经考虑了通过使用 ProxyFactoryBean 或类似的工厂 bean 显式创建 AOP 代理。

Infra 还允许我们使用“自动代理” bean 定义,它可以自动代理选定的 bean 定义。 这是建立在 Infra “bean 后处理器”基础设施之上的,它允许在容器加载时修改任何 bean 定义。

在这个模型中,你在 XML bean 定义文件中设置一些特殊的 bean 定义来配置自动代理基础设施。 这让你声明有资格进行自动代理的目标。你不需要使用 ProxyFactoryBean

有两种方法可以做到这一点:

  • 通过使用引用当前上下文中特定 bean 的自动代理创建者。

  • 一个值得单独考虑的自动代理创建的特殊情况:由源级元数据属性驱动的自动代理创建。

自动代理 Bean 定义

本节涵盖 infra.aop.framework.autoproxy 包提供的自动代理创建者。

BeanNameAutoProxyCreator

BeanNameAutoProxyCreator 类是一个 BeanPostProcessor,它自动为名称与文字值或通配符匹配的 bean 创建 AOP 代理。 以下示例显示了如何创建 BeanNameAutoProxyCreator bean:

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

ProxyFactoryBean 一样,有一个 interceptorNames 属性而不是拦截器列表,以允许原型 advisor 的正确行为。 命名的“拦截器”可以是 advisor 或任何 advice 类型。

与一般的自动代理一样,使用 BeanNameAutoProxyCreator 的主要目的是以最小的配置量将相同的配置一致地应用于多个对象。 这是将声明式事务应用于多个对象的流行选择。

名称匹配的 bean 定义,例如前面示例中的 jdkMyBeanonlyJdk,是具有目标类的普通 bean 定义。 AOP 代理是由 BeanNameAutoProxyCreator 自动创建的。相同的 advice 应用于所有匹配的 bean。 请注意,如果使用 advisor(而不是前面示例中的拦截器),pointcut 可能会以不同方式应用于不同的 bean。

DefaultAdvisorAutoProxyCreator

一个更通用且极其强大的自动代理创建者是 DefaultAdvisorAutoProxyCreator。 它会自动应用当前上下文中符合条件的 advisor,而无需在自动代理 advisor 的 bean 定义中包含特定的 bean 名称。 它提供了与 BeanNameAutoProxyCreator 相同的一致配置和避免重复的优点。

使用此机制涉及:

  • 指定一个 DefaultAdvisorAutoProxyCreator bean 定义。

  • 在相同或相关的上下文中指定任意数量的 advisor。请注意,这些必须是 advisor,而不是拦截器或其他 advice。 这是必要的,因为必须有一个 pointcut 来评估,以检查每个 advice 对候选 bean 定义的资格。

DefaultAdvisorAutoProxyCreator 自动评估每个 advisor 中包含的 pointcut,以查看它应该对每个业务对象(例如示例中的 businessObject1businessObject2)应用什么 advice(如果有)。

这意味着任意数量的 advisor 可以自动应用于每个业务对象。 如果任何 advisor 中的任何 pointcut 都不匹配业务对象中的任何方法,则该对象不会被代理。 随着为新的业务对象添加 bean 定义,如果需要,它们会自动被代理。

一般的自动代理具有使调用者或依赖项无法获得未被通知对象的优点。 在这个 ApplicationContext 上调用 getBean("businessObject1") 返回一个 AOP 代理,而不是目标业务对象。 (前面显示的“内部 bean”习语也提供了这种好处。)

以下示例创建一个 DefaultAdvisorAutoProxyCreator bean 和本节中讨论的其他元素:

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

<bean class="infra.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 提供对过滤(通过使用命名约定,以便仅评估某些 advisor,这允许在同一工厂中使用多个不同配置的 AdvisorAutoProxyCreator)和排序的支持。 Advisor 可以实现 infra.core.Ordered 接口以确保正确的顺序(如果这是一个问题)。 前面示例中使用的 TransactionAttributeSourceAdvisor 具有可配置的 order 值。默认设置是无序的。