Spring中的代理类

Spring在实现AOP时需要用到代理,有两种实现可选的代理方式,分别是JDK动态代理以及CGLIB代理。但这两种代理却又有着很大的区别。

一、两种实现代理方式的介绍

  1. JDK动态代理

    源自Java纯正血统,属于Java SE规范中的API。实现动态代理有如下四步骤:

    • 通过实现 InvocationHandler 接口创建自己的调用处理器;
    • 通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类;
    • 通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;
    • 通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。
  2. GCLIB代理
    • cglib(Code Generation Library)是一个强大的、高性能、高质量的Code生成类库。它可以在运行期扩展Java类与实现Java接口。
    • cglib封装了asm,可以在运行期动态生成新的class。
    • cglib用于AOP,JDK中的proxy必须基于接口,cglib却没有这个限制。

二、两种实现方式在Spring应用中的区别

  1. 如果目标对象实现了接口,默认情况下会采用JDK动态代理实现AOP
  2. 如果目标对象实现了接口,可以强制使用CGLIB实现AOP
  3. 如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换
  4. JDK动态代理只能对实现了接口的类生成代理,而不能针对类。它是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。
  5. CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,因为是继承,所以该类或方法最好不要声明成final。cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
  6. JDK动态代理生成的代理类并不是被代理类的子类,它只是实现了被代理类对应接口的一个匿名类,所以接口中没有的方法是不可用的,而且代理出来的类无法用被代理类的变量接收,但CGLIB确是被代理类的子类,所以被代理类的变量能够接收代理出来的类。

 三、如何强制使用CGLIB实现AOP

  Spring在实现AOP时需要用到代理,但默认情况下,如果目标对象实现了接口,会采用JDK动态代理来实现。我们需要用以下两部来强制使用CGLIB。

  1. 添加CGLIB库,SPRING_HOME/cglib/*.jar
  2. 在spring配置文件中加入<aop:aspectj-autoproxy proxy-target-class="true"/>

 

 

 

posted on 2017-10-19 11:42  笑看风云变幻  阅读(3570)  评论(0编辑  收藏  举报