Spring强制使用CGLIB代理事务

摘要:
以下代码是Spring的判断逻辑//org。弹簧框架。aop。frameworkDefaultAopProxyFactory//参数AdvisedSupport是与Spring AOP配置相关的类publicAopProxycreateAopProxythrowsAopConfigException{//如果{如果(!因此,默认情况下,如果目标对象没有实现任何接口,Spring将选择CGLIB代理,并且它生成的动态代理对象是目标类的子类。默认情况下也可以手动配置一些选项,以使Spring使用CGLIB代理。
 Spring强制使用CGLIB代理事务
 
springaopjdkreferenceclasspath
Spring1.2:
将事务代理工厂[TransactionProxyFactoryBean] 或 自动代理拦截器[BeanNameAutoProxyCreator]
的 proxyTargetClass 属性,设置为true,则使用CGLIB代理,此属性默认为false,使用JDK动态代理.
以下引用 Spring Framework reference 2.0.5:
Spring2.0:

Spring AOP部分使用JDK动态代理或者CGLIB来为目标对象创建代理。(建议尽量使用JDK的动态代理)

如果被代理的目标对象实现了至少一个接口,则会使用JDK动态代理。所有该目标类型实现的接口都将被代理。若该目标对象没有实现任何接口,则创建一个CGLIB代理。

如果你希望强制使用CGLIB代理,(例如:希望代理目标对象的所有方法,而不只是实现自接口的方法)那也可以。但是需要考虑以下问题:

无法通知(advise)Final 方法,因为他们不能被覆写。 
你需要将CGLIB 2二进制发行包放在classpath下面,与之相较JDK本身就提供了动态代理 
强制使用CGLIB代理需要将 |aop:config| 的 proxy-target-class 属性设为true:

|aop:config proxy-target-class="true"|
...
|/aop:config|

当需要使用CGLIB代理和@AspectJ自动代理支持,请按照如下的方式设置 |aop:aspectj-autoproxy| 的 proxy-target-class 属性:

|aop:aspectj-autoproxy proxy-target- /|

而实际使用的过程中才会发现细节问题的差别,The devil is in the detail.JDK动态代理:其代理对象必须是某个接口的实现,它是通过在运行期间创建一个接口的实现类来完成对目标对象的代理。
CGLIB代理:实现原理类似于JDK动态代理,只是它在运行期间生成的代理对象是针对目标类扩展的子类。CGLIB是高效的代码生成包,底层是依靠ASM(开源的java字节码编辑类库)操作字节码实现的,性能比JDK强。
Spring是依靠什么来判断采用哪种代理策略来生成AOP代理呢?以下代码就是Spring的判断逻辑  

    //org.springframework.aop.framework.DefaultAopProxyFactory   
    //参数AdvisedSupport 是Spring AOP配置相关类   
    public AopProxy createAopProxy(AdvisedSupport advisedSupport)   
            throws AopConfigException {   
        //在此判断使用JDK动态代理还是CGLIB代理   
        if (advisedSupport.isOptimize() || advisedSupport.isProxyTargetClass()   
                || hasNoUserSuppliedProxyInterfaces(advisedSupport)) {   
            if (!cglibAvailable) {   
                throw new AopConfigException(   
                        "Cannot proxy target class because CGLIB2 is not available. "  
                                + "Add CGLIB to the class path or specify proxy interfaces.");   
              }   
            return CglibProxyFactory.createCglibProxy(advisedSupport);   
          } else {   
            return new JdkDynamicAopProxy(advisedSupport);   
          }   
      }  

advisedSupport.isOptimize()与advisedSupport.isProxyTargetClass()默认返回都是false,所以在默认情况下目标对象有没有实现接口决定着Spring采取的策略,当然可以设置advisedSupport.isOptimize()或者advisedSupport.isProxyTargetClass()返回为true,这样无论目标对象有没有实现接口Spring都会选择使用CGLIB代理。

所以在默认情况下,如果一个目标对象如果实现了接口Spring则会选择JDK动态代理策略动态的创建一个接口实现类(动态代理类)来代理目标对象,可以通俗的理解这个动态代理类是目标对象的另外一个版本,所以这两者之间在强制转换的时候会抛出java.lang.ClassCastException。而所以在默认情况下,如果目标对象没有实现任何接口,Spring会选择CGLIB代理, 其生成的动态代理对象是目标类的子类。

上说的是默认情况下,也可以手动配置一些选项使Spring采用CGLIB代理。 
org.springframework.transaction.interceptor.TransactionProxyFactoryBean是org.springframework.aop.framework. ProxyConfig的子类,所以可以参照ProxyConfig里的一些设置如下所示,将optimize和proxyTargetClass任意一个设置为true都可以强制Spring采用CGLIB代理。

如果当需要使用CGLIB代理和@AspectJ自动代理支持,请按照如下的方式设置 |aop:aspectj-autoproxy| 的 proxy-target-class 属性: 
|aop:aspectj-autoproxy proxy-target- /|

这样使用CGLIB代理也就不会出现前面提到的ClassCastException问题了,也可以在性能上有所提高,关键是对于代理对象是否继承接口可以统一使用。

免责声明:文章转载自《Spring强制使用CGLIB代理事务》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Linux命令(1)-创建文件Javassist/ASM 框架比较下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

什么是JDK的SPI机制

什么是SPI和API  Application Programming Interface (API)? The API is the description of classes/interfaces/methods/... that you call and use to achieve a goal, and the SPI is the desc...

改变websphere默认jdk为1.5

     在WAS6.1版本中使用JDK5.0,但是如果在JSP中嵌入的代码包含JDK5.0的新特性,编译的时候会出错。所以应用程序部署Was完成之后需要设置相应的JSP引擎配置参数,具体如下: “jdkSourceLevel” 是在 WasV6.1 中引入的支持 JDK 5 新特性的 JSP 引擎参数。此参数的缺省值为 13。以下是 “jdkSource...

Oracle安装

参考:https://blog.csdn.net/wudiyong22/article/details/78904361 一、Oracle下载 注意Oracle分成两个文件,下载完后,将两个文件解压到同一目录下即可。 路径名称中,最好不要出现中文,也不要出现空格等不规则字符。百度云盘:https://pan.baidu.com/s/14cBI8mAro7r...

jre安装配置!

  通常安装java开发环境都是jdk ,jre 一起安装,配置变量!分享一下只安装jre的配置!   去官网下载jre,      按提示安装成功!   和jdk配置一样 ,首先配置一下:JRE_HOME=C:Program Files (x86)Javajre6,   然后在path后面添加 %JRE_HOME%in;   配置完之后  进入cmd命令...

开放API接口签名验证

我们开放的api接口如果不做验证,完全暴露在外面是极其不安全的,所以我们要把我们的接口进行签名。 那签名有什么意义呢? 1、保证数据未被篡改 2、请求来源身份合法性 3、请求的唯一性 (不可复制) 那我们该如何实施呢: 1、首先我们得给客户端分配对应的key和secret 2、客户端访问数据接口之前需要用md5加密算法进行一次签名,签名内容是把我们提交的值...

浪潮各机型管理芯片BMC IP(智能平台管理接口)设置

NF5240m3/NF5140m3/NF5280m3/SA5212H2/NP5540M3NF5270M3/NF5170M3/NF8420m3 IPMI主板集成管理芯片BMC IP 设置开机按DEL键进入BIOS设置选择"Server Mgmt"---"BMC Network Configuration"---"lan channel 1/2"---"sta...