JDK动态代理与CGLib动态代理

JDK动态代理:

a、先定义一个接口,这个接口中的方法是“目标方法”

package com.brickworkers;

public interface Sky {

    public void rain();

}

 

b、接着写一个这个接口的具体实现:

package com.brickworkers;

public class SkyImpl implements Sky{

    @Override
    public void rain() {
        System.out.println("it`s raining");
    }


}

 

c、如果要完成动态代理,首先需要定义一个InvocationHandler接口的子类:

package com.brickworkers;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class MyInvocationHandler implements InvocationHandler {

    //目标对象
    private Object obj = null;


    //获取目标对象的代理对象
    public Object getProxy(Object obj){
        this.obj = obj;
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
    }

    //控制执行目标对象的方法
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("目标对象方法执行之前");
        Object result = method.invoke(obj, args);
        System.out.println("目标对象方法执行之后");
        return result;
    }

}

 

d:JDK动态代理测试类:

package com.brickworkers;

public class ProxyTest {

    public static void main(String[] args) {
        //实例化InvocationHandler
        MyInvocationHandler myInvocationHandler = new MyInvocationHandler();
        //生产代理对象
        Sky sky = (Sky) myInvocationHandler.getProxy(new SkyImpl());
        sky.rain();
    }

}

//执行结果:  目标对象方法执行之前
//            it`s raining
//          目标对象方法执行之后

 

为什么JDK动态代理只能局限于接口呢?查阅了一些技术文档和JDK动态代理的源码,发现在反编译产生的proxyTest.class中,类的定义如下:

import dynamic.proxy.UserService;  
import java.lang.reflect.*;  

public final class $ProxyTest extends Proxy  
    implements Sky
{ 
    ......
}

从反编译的源码可以看出,proxyTest继承了Proxy,然而在Java中只支持单继承,但是可以实现多个接口,所以JDK动态代理只能局限于接口。

那么JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类,要实现动态代理要怎么办呢?这个时候就需要CGLib动态代理了。

 

CGLib动态代理:

CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有分类方法的调用,顺势织入和横切逻辑。-http://blog.csdn.net/yakoo5/article/details/9099133/

 

点击下载编写CGlib动态代理测试所需jar包

 

a、定义一个目标对象:

package com.brickworkers;

public class Color {

    public void showColor(){
        System.out.println("red");
    }

}

 

b、如果要完成动态代理,首先需要定义一个MethodInterceptor接口的子类:

package com.brickworkers;

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 MyCglib implements MethodInterceptor {

    //目标对象
    private Object obj = null;

    public Object getProxy(Object obj){
        this.obj = obj;
        Enhancer enhancer = new Enhancer();  
        enhancer.setSuperclass(obj.getClass());
        // 回调方法  
        enhancer.setCallback(this);  
        // 创建代理对象  
        return enhancer.create();

    }

    @Override
    public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("目标对象方法执行之前");
        Object result = methodProxy.invoke(obj, args);
        System.out.println("目标方法执行之后");
        return result;
    }

}

c、CGLib动态代理测试类:

package com.brickworkers;

public class CGLibTest {

    public static void main(String[] args) {
        MyCglib myCglib = new MyCglib();
        Color color = (Color) myCglib.getProxy(new Color());
        color.showColor();
    }
}
//执行结果:目标对象方法执行之前
//              red
//          目标方法执行之后

因为CGLib动态代理是创建一个子类来实现的,那么对于继承的定义,final类是无法进行代理的。

 

posted @ 2018-03-05 20:33  _AlbertWang  阅读(270)  评论(0编辑  收藏  举报