您的位置:首页 > 编程语言 > Java开发

JDK动态代理与CGLib动态代理

2018-03-05 20:33 225 查看

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类是无法进行代理的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: