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

JDK动态代理和CGLiB动态代理

2016-03-13 10:43 120 查看
JDK动态代理
JDK动态代理要求类必须实现某一接口,代理类是同一接口的实现类。
JDK动态代理主要涉及两个类:Proxy和InvocationHandler。InvocationHandler是一个接口,可以通过实现该接口定义横切逻辑,并通过反射机制调用目标类的代码,动态的将横切逻辑与业务逻辑交织在一起。Proxy利用InvocationHandler动态创建一个符合某一接口的实例,生成目标类的代理对象。
public class MyInvocationHandler implements InvocationHandler {
private Object target;
public MyInvocationHandler(Object target){
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) {
begin();
Object obj = method.invoke(target, args);
end();
return obj;
}
}

创建代理实例
public class Test {
public static void main(String [] args){
Target target = new TargetImpl();
MyInvocationHandler handler = new MyInvocationHandler(target);
Target proxy = (Target) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getInterfaces(),
handler);
proxy.test();
}
}


CGLiB动态代理
JDK动态代理有一个缺点,就是它只能为接口创建代理实例。对于没有通过接口实现业务逻辑的类,通过CGLiB来实现代理。
CGLiB采用非常底层的字节码技术,可以为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,并顺势织入横切逻辑。
public class CglibProxy implements MethodInterceptor {
private Enhancer enhancer = new Enhancer();
public Object getProxy(Class clazz) {
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return enhancer.create();
}
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) {
begin();
Object result = proxy.invokeSuper(obj, args);
end();
return result;
}
}

创建动态代理
public class Test {
public static void main(String [] args) {
CglibProxy proxy = new CglibProxy();
TargetImpl target = (TargetImpl) proxy.getProxy(TargetImpl.class);
target.test();

}
}


对比
CGLiB所创建的动态代理对象要比JDK所创建的动态代理对象的性能要高出10倍,但CGLiB创建动态代理所花费的时间却比JDK动态代理多8倍。
对于singleton的代理对象或具有实例池的代理,因为无需频繁的创建代理对象,所以适合使用CGLiB代理,繁殖则使用JDK动态代理。
由于CGLIB动态代理采用动态创建子类的方式生成代理对象,所以不能对目标类中 的final方法进行代理
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: