ProxyFactoryBean 代理工具类存在着如下缺点:
(1)一个代理对象只能代理一个 Bean,即如果有两个 Bean 同时都要织入同一个切面,这时,不仅要配置这两个 Bean,即两个目标对象,同时还要配置两个代理对象。
(2)在客户类中获取 Bean 时,使用的是代理类的 id,而非我们定义的目标对象 Bean 的 id。我们真正想要执行的应该是目标对象。从形式上看,不符合正常的逻辑。
Spring 提供了自动代理生成器,用于解决 ProxyFactoryBean 的问题。常用的自动代理生成器有两个:
- 默认 advisor 自动代理生成器
- Bean 名称自动代理生成器
注意:
自动代理生成器均继承自 Bean 后处理器 BeanPostProcessor。容器中所
有 Bean 在初始化时均会自动执行 Bean 后处理器中的方法,故其无需 id 属性。所以自动代理生成器的 Bean 也没有 id 属性,客户类直接使用目标对象 bean 的 id。
自动代理生成器,均是继承自 BeanPostProcessor, Bean 后处理器。查看源码:
默认 Advisor 自动代理生成器
DefaultAdvisorAutoProxyCreator 代理的生成方式是,将所有的目标对象与 Advisor 自动结合,生成代理对象。无需给生成器做任何的注入配置。注意,只能与 Advisor 配合使用。
<!-- 注册自动代理生成器 -->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
缺点:
(1)不能选择目标对象
(2)不能选择切面类型,切面只能是advisor
(3)不能选择advisor,所以advisor均将被作为切面织入到目标方法
Bean 名称自动代理生成器
BeanNameAutoProxyCreator 的代理生成方式是,根据 bean 的 id,来为符合相应名称的类生成相应代理对象,且切面既可以是顾问 Advisor 又可以是通知 Advice。
<!-- 注册自动代理生成器 -->
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames" value="someService"/>
<property name="interceptorNames" value="myAdvisor"/>
</bean>
缺点:
1)若存在多个目标对象,就需要使用多次ProxyFactoryBean来创建多个代理对象,这会使配置文件变得臃肿,不便于管理
2)用户真正想调用的是目标对象,而真正可以调用的却是代理对象,这不符合正常的逻辑