JDK动态代理与CGLib动态代理

JDK动态代理:

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

package com.brickworkers;

public interface Sky {

    public void rain();

}

 

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

package com.brickworkers;

public class SkyImpl implements Sky{

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


}

 

c、若是要完成动态代理,首先须要定义一个InvocationHandler接口的子类:ide

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中,类的定义以下:this

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

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

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

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

 

CGLib动态代理:

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

 

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

 

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类是没法进行代理的。

相关文章
相关标签/搜索