文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Spring使用ProxyFactoryBean创建代理对象

2024-11-30 18:27

关注

概述

在Spring中创建AOP代理的基本方法是使用org.springframework.aop.framework.ProxyFactoryBean。这提供了对切入点、应用的任何通知及其顺序的完全控制。但是,如果你不需要这种控制,则有更简单的选项更可取。

和其他Spring FactoryBean实现一样,ProxyFactoryBean引入了一个间接层。如果定义了一个名为foo的ProxyFactoryBean,那么引用foo的对象不会看到ProxyFactoryBean实例本身,而是看到一个由ProxyFactoryBean中的getObject()方法实现创建的对象。此方法创建封装目标对象的AOP代理。

使用ProxyFactoryBean或另一个支持IoC的类来创建AOP代理的最重要的好处之一是,IoC也可以管理Advice和Pointcut。这是一个强大的特性,可以实现某些用其他AOP框架难以实现的方法。例如,通知本身可以引用应用程序对象(目标之外,它应该在任何AOP框架中可用),受益于依赖项注入提供的所有可插拔性。

ProxyFactoryBean 属性

和Spring提供的大多数FactoryBean实现一样,ProxyFactoryBean类本身就是一个JavaBean。它的属性用于:

ProxyFactoryBean特有的其他属性包括:

基于JDK和CGLIB的代理

​ProxyFactoryBean如何选择为特定目标对象(要代理的对象)创建基于JDK的代理或基于CGLIB的代理的最终文档。

如果要代理的目标对象的类(以下简称为目标类)没有实现任何接口,则创建一个基于cglib的代理。这是最简单的场景,因为JDK代理是基于接口的,没有接口意味着JDK代理根本不可能。你可以插入目标bean并通过设置interceptorNames属性来指定拦截器列表。注意,即使将ProxyFactoryBean的proxyTargetClass属性设置为false,也会创建一个基于cglib的代理。

如果目标类实现了一个(或多个)接口,则创建的代理类型取决于ProxyFactoryBean的配置。

如果ProxyFactoryBean的proxyTargetClass属性被设置为true,则会创建一个基于cglib的代理。这是有道理的,也符合最小意外原则。即使ProxyFactoryBean的proxyInterfaces属性被设置为一个或多个完全限定的接口名,proxyTargetClass属性被设置为true这一事实也会导致基于cglib的代理生效。

如果将ProxyFactoryBean的proxyInterfaces属性设置为一个或多个完全限定的接口名,则创建一个基于jdk的代理。创建的代理实现了在proxyInterfaces属性中指定的所有接口。如果目标类碰巧实现了比proxyInterfaces属性中指定的更多的接口,那也没什么问题,但返回的代理不会实现这些额外的接口。

如果ProxyFactoryBean的proxyInterfaces属性没有被设置,但是目标类确实实现了一个(或多个)接口,那么ProxyFactoryBean会自动检测到目标类实际上至少实现了一个接口,并且创建了一个基于jdk的代理。实际被代理的接口是目标类实现的所有接口。实际上,这相当于为目标类的proxyInterfaces属性提供一个列表,其中包含目标类实现的所有接口。然而,这样做工作量大大减少,也不容易出现排版错误。

代理接口

考虑一个使用ProxyFactoryBean的简单例子。这个例子涉及:

<bean id="personTarget" class="com.mycompany.PersonImpl">
<property name="name" value="Tony"/>
<property name="age" value="51"/>
bean>

<bean id="myAdvisor" class="com.mycompany.MyAdvisor">
<property name="someProperty" value="Custom string property value"/>
bean>

<bean id="debugInterceptor" class="org.springframework.aop.interceptor.DebugInterceptor">
bean>

<bean id="person" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces" value="com.mycompany.Person"/>
<property name="target" ref="personTarget"/>
<property name="interceptorNames">
<list>
<value>myAdvisorvalue>
<value>debugInterceptorvalue>
list>
property>
bean>

注意,interceptorNames属性接受一个字符串列表,其中包含当前工厂中拦截器或顾问的bean名称。你可以使用顾问,拦截器,返回之前,之后,并抛出建议对象。

前面给出的person bean定义可以代替person实现,如下所示:

Person person = (Person) factory.getBean("person");

同一个IoC上下文中的其他bean可以表达对它的强类型依赖,就像普通Java对象一样。如下面的例子所示:

<bean id="personUser" class="com.mycompany.PersonUser">
<property name="person"><ref bean="person"/>property>
bean>

这个例子中的PersonUser类公开了一个Person类型的属性。就它所关心的而言,AOP代理可以透明地代替“真实的”人实现。但是,它的类将是一个动态代理类。

代理类

如果需要代理一个类,而不是一个或多个接口,该怎么办?

想象一下,在我们前面的例子中,没有Person接口。我们需要建议一个名为Person的类,它没有实现任何业务接口。在这种情况下,你可以配置Spring使用CGLIB代理,而不是动态代理。为此,将前面给出的ProxyFactoryBean的proxyTargetClass属性设置为true。虽然最好是针对接口而不是类进行编程,但在处理遗留代码时,能够建议不实现接口的类可能很有用。(一般来说,Spring不是规定性的。虽然它使应用良好的实践变得容易,但它避免了强制使用特定的方法。)

如果你愿意,你可以在任何情况下强制使用CGLIB,即使你有接口。

CGLIB代理通过在运行时生成目标类的子类来工作。Spring将这个生成的子类配置为将方法调用委托给原始目标。子类用于实现装饰器模式,在建议中编织。

CGLIB代理一般应该对用户透明。但是,有一些问题需要考虑:

使用“全局”顾问(Advisor)

通过在拦截器名称后面附加一个星号,所有bean名称与星号之前的部分匹配的顾问都被添加到顾问链中。如果你需要添加一组标准的“全局”顾问,这可以派上用场。下面的例子定义了两个全局advisor:

<bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="service"/>
<property name="interceptorNames">
<list>
<value>global*value>
list>
property>
bean>
<bean id="global_debug" class="org.springframework.aop.interceptor.DebugInterceptor"/>
<bean id="global_performance" class="org.springframework.aop.interceptor.PerformanceMonitorInterceptor"/>
来源:今日头条内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯