大话java之JDK动态代理和CGLIB动态代理

来源:互联网 发布:一致性哈希 java实现 编辑:程序博客网 时间:2024/05/21 13:22

上一篇讲到了java的动态代理和JDK动态代理的使用和原理。这一篇要讲讲cglib代理,和jdk代理使用上的一个重要区别是jdk代理必须是以接口为委托类。那么在委托类不是接口的情况下,就可以使用gclib动态代理了。
gclib的实现代码如下:
1)委托类

public class TestImplement {    @Override    public void business() {        try{            System.out.println("do the busniess");            Thread.sleep(200);        }catch (Exception e) {            e.printStackTrace();        }    }}

2)处理类

import java.lang.reflect.Method;import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;public class GclibLoggerInterceptor implements MethodInterceptor {    private Object target;// 目标类    public Object getInstance(Object target) {        this.target = target;         Enhancer enhancer = new Enhancer();          enhancer.setSuperclass(this.target.getClass());          // 回调方法          enhancer.setCallback(this);          // 创建代理对象          return enhancer.create();      }    //这是一个简单的日志处理类,会记录方法的执行时间和耗时    @Override    public Object intercept(Object obj, Method method, Object[] args,              MethodProxy proxy) throws Throwable {        Long timeStart = System.currentTimeMillis();        System.out.println("-- invoke start---timeStart="+timeStart);        Object result = proxy.invokeSuper(obj, args);        System.out.println("-- invoke finish---takes="+(System.currentTimeMillis()-timeStart));//记录方法的调用耗时        return result;    }}

3)测试代码:

        GclibLoggerInterceptor interceptor = new GclibLoggerInterceptor();        TestImplement testImplement = (TestImplement)interceptor.getInstance(new TestImplement());        testImplement.business();

输出结果:

– invoke start—timeStart=1504428278274
do the busniess
– invoke finish—takes=231

和jdk代理的区别,主要在于处理类的实现有些不同,委托类不限于接口。

2者的区别:

1.JDK动态代理
此时代理对象和目标对象实现了相同的接口,目标对象作为代理对象的一个属性,具体接口实现中,可以在调用目标对象相应方法前后加上其他业务处理逻辑。

代理模式在实际使用时需要指定具体的目标对象,如果为每个类都添加一个代理类的话,会导致类很多,同时如果不知道具体类的话,怎样实现代理模式呢?这就引出动态代理。

JDK动态代理只能针对实现了接口的类生成代理。

2.CGLIB代理
CGLIB(CODE GENERLIZE LIBRARY)代理是针对类实现代理,

主要是对指定的类生成一个子类,覆盖其中的所有方法,所以该类或方法不能声明称final的。

JDK动态代理和CGLIB代理生成的区别
JDK动态代理只能对实现了接口的类生成代理,而不能针对类 。
CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法 。
因为是继承,所以该类或方法最好不要声明成final ,final可以阻止继承和多态。

动态代理的应用
AOP(Aspect-OrientedProgramming,面向切面编程),AOP包括切面(aspect)、通知(advice)、连接点(joinpoint),实现方式就是通过对目标对象的代理在连接点前后加入通知,完成统一的切面操作。

实现AOP的技术,主要分为两大类:

一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;

二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。

Spring提供了两种方式来生成代理对象: JDKProxy和Cglib,具体使用哪种方式生成由AopProxyFactory根据AdvisedSupport对象的配置来决定。

默认的策略是如果目标类是接口,则使用JDK动态代理技术,如果目标对象没有实现接口,则默认会采用CGLIB代理。

如果目标对象实现了接口,可以强制使用CGLIB实现代理(添加CGLIB库,并在spring配置中加入)。

原创粉丝点击