Spring Aop(十三)——ProxyFactoryBean创建代理对象

简介: ProxyFactoryBean创建代理对象 ProxyFactoryBean实现了Spring的FactoryBean接口,所以它跟Spring中的其它FactoryBean一样,都是基于工厂模式来获取一个bean的。

ProxyFactoryBean创建代理对象

ProxyFactoryBean实现了Spring的FactoryBean接口,所以它跟Spring中的其它FactoryBean一样,都是基于工厂模式来获取一个bean的。ProxyFactoryBean就是用来获取一个对象的代理对象的FactoryBean。它也是继承自ProxyCreatorSupport类的,所以它的功能基本跟ProxyFactory差不多,只是ProxyFactory是用于编程式的创建代理对象。而ProxyFactoryBean用于在Spring的bean容器中创建基于bean的代理对象。通常一个简单的ProxyFactoryBean配置大概会是如下这样。

<bean id="proxyFactoryBeanTestService" 
  class="org.springframework.aop.framework.ProxyFactoryBean">
  <property name="target"><!-- 指定被代理的对象 -->
    <bean class="com.elim.learn.spring.aop.service.ProxyFactoryBeanTestService"/>
  </property>
  <property name="proxyTargetClass" value="true"/><!-- 指定启用基于Class的代理 -->
  <!-- 指定生成的代理对象需要绑定的Advice或Advisor在bean容器中的名称 -->
  <property name="interceptorNames">
    <list>
      <value>logAroundAdvice</value>
    </list>
  </property>
</bean>

在上面的示例中我们被代理的对象对应的Class是com.elim.learn.spring.aop.service.ProxyFactoryBeanTestService,其是一个没有实现任何接口的Class,所以我们生成的代理对象最终会是基于CGLIB的代理。我们需要指定proxyTargetClass="true",以表示我们是倾向于使用CGLIB代理的,对于上面的配置实际上就是告诉Spring我们要使用CGLIB代理。虽然这里我们不指定proxyTargetClass="true"时,Spring可能也会给我们使用CGLIB代理,为什么这里说是可能呢?因为ProxyFactoryBean默认生成的bean都是单例、且在生成bean时会自动检测被代理对象实现的接口,而且proxyTargetClass默认是false,这种情况下ProxyFactoryBean就会自动检测被代理对象的实现的接口。按理来说我们的bean是一个没有实现接口的bean,Spring给我们去找它实现的接口是找不出来的,但是我们知道Spring的Aop是会自动为我们的对象实现一些接口的。简单的说如果我们的bean容器中配置了其它的Advisor,那么我们指定的target对象有可能就不是一个原始的bean,而是一个已经被Aop代理过的bean对象,这种bean对象,Spring Aop默认会为其实现一个Advised接口。所以使用ProxyFactoryBean时,如果我们的代理对象类是没有实现接口的,或者我们期望生成代理对象时是基于Class的,而不是基于Interface的,我们最好明确的指定proxyTargetClass="true",而不是寄希望于Spring的自动决定机制。 指定被代理对象时,除了可以直接指定target外,我们还可以通过targetName指定被代理对象在bean容器中的bean名称。 在上面的示例中我们通过interceptorNames属性指定了生成的代理对象需要应用的Advisor/Advice对应于bean容器中的bean的名称。跟ProxyFactory一样,如果我们指定的是Advice对象,则其会转换为一个匹配所有方法调用的Advisor与代理对象绑定。 在指定intercepterNames时我们也可以通过“*”指定所有beanName以XX开始的Advisor/Advice,如我们的bean容器中同时拥有“abc1Advisor”、“abc2Advisor”两个Advisor,我们期望创建的ProxyFactoryBean同时应用这两个Advisor,那我们可以不用单独指定两次,而是一次性把interceptorNames指定的一个beanName为“abc*”。需要注意的是“*”只能定义在beanName的末端。

<bean id="proxyFactoryBeanTestService" 
  class="org.springframework.aop.framework.ProxyFactoryBean">
  <property name="target"><!-- 指定被代理的对象 -->
    <bean class=" com.elim.learn.spring.aop.service.ProxyFactoryBeanTestService"/>
  </property>
  <property name="proxyTargetClass" value="true"/><!-- 指定启用基于Class的代理 -->
  <!-- 指定生成的代理对象需要绑定的Advice或Advisor在bean容器中的名称 -->
  <property name="interceptorNames">
    <list>
      <value>abc*</value>
    </list>
  </property>
</bean>

其它配置信息

  • exposeProxy:属于从ProxyCreatorSupport继承过来的属性,用于定义是否需要在调用代理对象时把代理对象发布到AopContext,默认是false
  • singleton:用来指定ProxyFactoryBean生成的bean是否是单例的,默认是true。该值对应于FactoryBean的isSingleton()接口方法的返回值。
  • frozen:属于从ProxyCreatorSupport继承过来的属性,用于指定代理对象被创建后是否还允许更改代理配置,通过Advised接口更改。true表示不允许,默认是false。
  • autodetectInterfaces:表示是否在生成代理对象时需要启用自动检测被代理对象实现的接口,默认是true
  • proxyInterfaces:基于接口的代理时指定需要代理的接口。
  • interfaces:基于接口的代理时指定需要代理的接口,属于从ProxyCreatorSupport继承过来的。 关于ProxyFactoryBean的更多配置项信息可以参考Spring的API文档或ProxyFactoryBean的源代码。
    (注:本文是基于Spring4.1.0所写,Elim写于2017年5月10日)
目录
相关文章
|
3天前
|
存储 缓存 Java
Spring高手之路23——AOP触发机制与代理逻辑的执行
本篇文章深入解析了Spring AOP代理的触发机制和执行流程,从源码角度详细讲解了Bean如何被AOP代理,包括代理对象的创建、配置与执行逻辑,帮助读者全面掌握Spring AOP的核心技术。
8 3
Spring高手之路23——AOP触发机制与代理逻辑的执行
|
13天前
|
Java 编译器 Spring
Spring AOP 和 AspectJ 的区别
Spring AOP和AspectJ AOP都是面向切面编程(AOP)的实现,但它们在实现方式、灵活性、依赖性、性能和使用场景等方面存在显著区别。‌
28 2
|
15天前
|
Java Spring
获取spring工厂中bean对象的两种方式
获取spring工厂中bean对象的两种方式
14 1
|
15天前
|
前端开发 Java Spring
【Spring】“请求“ 之传递单个参数、传递多个参数和传递对象
【Spring】“请求“ 之传递单个参数、传递多个参数和传递对象
60 2
|
18天前
|
存储 Java 程序员
SpringIOC和DI的代码实现,Spring如何存取对象?@Controller、@Service、@Repository、@Component、@Configuration、@Bean DI详解
本文详细讲解了Spring框架中IOC容器如何存储和取出Bean对象,包括五大类注解(@Controller、@Service、@Repository、@Component、@Configuration)和方法注解@Bean的用法,以及DI(依赖注入)的三种注入方式:属性注入、构造方法注入和Setter注入,并分析了它们的优缺点。
14 0
SpringIOC和DI的代码实现,Spring如何存取对象?@Controller、@Service、@Repository、@Component、@Configuration、@Bean DI详解
|
12天前
|
XML Java 数据格式
Spring的IOC和AOP
Spring的IOC和AOP
31 0
|
1月前
|
SQL 监控 druid
springboot-druid数据源的配置方式及配置后台监控-自定义和导入stater(推荐-简单方便使用)两种方式配置druid数据源
这篇文章介绍了如何在Spring Boot项目中配置和监控Druid数据源,包括自定义配置和使用Spring Boot Starter两种方法。
|
10天前
|
人工智能 自然语言处理 前端开发
SpringBoot + 通义千问 + 自定义React组件:支持EventStream数据解析的技术实践
【10月更文挑战第7天】在现代Web开发中,集成多种技术栈以实现复杂的功能需求已成为常态。本文将详细介绍如何使用SpringBoot作为后端框架,结合阿里巴巴的通义千问(一个强大的自然语言处理服务),并通过自定义React组件来支持服务器发送事件(SSE, Server-Sent Events)的EventStream数据解析。这一组合不仅能够实现高效的实时通信,还能利用AI技术提升用户体验。
53 2
|
2月前
|
缓存 Java Maven
Java本地高性能缓存实践问题之SpringBoot中引入Caffeine作为缓存库的问题如何解决
Java本地高性能缓存实践问题之SpringBoot中引入Caffeine作为缓存库的问题如何解决
|
10天前
|
SQL JSON Java
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块
这篇文章介绍了如何在Spring Boot项目中整合MyBatis和PageHelper进行分页操作,并且集成Swagger2来生成API文档,同时定义了统一的数据返回格式和请求模块。
22 1
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块