下文我们谈论关于Java中的两种代理方式:JDK的动态代理、GBLIB代理,本文不在讨论代理的好处和使用场合,而是对比两种代理方式
JDK的动态代理:
接口:
public interface Gril {
void talkWithBoy();
}
实现类:
public class AGril implements Gril{
public void talkWithBoy(){
System.out.println("I love you...........");
}
}
创建代理的类:
//此类要求必须实现InvocationHandler接口,并实现其invoke方法
public class JDKProxy implements InvocationHandler {
private Object target=null;
// 创建代理对象
// 参数target为被代理的对象
public Object createProxyObject(Object target) {
if (target == null)
return null;
else{
this.target=target;
//参数:被代理对象的类加载器、被代理对象所在类实习的接口,代理对象本身
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);
}
}
//实现InvocationHandler接口的方法,用于代替代理对象的方法的执行
public Object invoke(Object proxy, Method method, Object[] params)
throws Throwable {
System.out.println("JDK代理开始...............");
Object result=null;
result=method.invoke(target, params);
System.out.println("JDK代理结束...............");
return result;
}
}
测试主类:
public class TestProxy {
public static void main(String[] args) {
JDKProxy jdkProxy=new JDKProxy();
/* 注意点:JDK的动态代理,要求被代理的类必须实现接口,否则下面一行会出项错误
ClassCastException异常,而且必须以多态方式定义Gril对象
*/
Gril a1=new AGril();
Gril a2=(Gril)jdkProxy.createProxyObject(a1) ;
a2.talkWithBoy();
}
}
打印结果:
JDK代理开始...............
I love you...........
JDK代理结束...............
CGLIB代理(需要导入cglib所需要的包(spring的自带项目中存在)):
一般业务类:
public class ABoy {
public void talkWithGril(){
System.out.println("I love you too...........");
}
}
创建代理的类:
//此类必须实现MethodInterceptor接口,并实现其intercept的方法
public class CGLIBProxy implements MethodInterceptor{
//被代理的对象
private Object target=null;
//创建代理对象
public Object creatProxyObject(Object target){
if(target==null)
return null;
else{
this.target=target;
//借助Enhancer类生产代理对象
Enhancer enhancer=new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
//返回创建好的代理对象
return enhancer.create();
}
}
//实现MethodInterceptor接口的方法,用于代替代理对象的方法的执行
public Object intercept(Object proxy, Method method, Object[] params,
MethodProxy methodProxy) throws Throwable {
System.out.println("CGLIB代理开始...............");
Object result=null;
result=method.invoke(target, params);
System.out.println("CGLIB代理结束...............");
return result;
}
}
测试主类:
public class TestProxy {
public static void main(String[] args) {
CGLIBProxy cglibProxy=new CGLIBProxy();
ABoy a=new ABoy();
ABoy b=(ABoy) cglibProxy.creatProxyObject(a);
b.talkWithGril();
}
}
测试结果:
CGLIB代理开始...............
I love you too...........
CGLIB代理结束...............
两种代理方式的区别和联系:
联系:创建代理的类都实现了对应接口并实现了相应的方法,都必须存在被代理对象这个属性。
区别:实现的接口不同,JDK动态代理实现的是InvocationHandler,而CGLIB实现的是MethodInterceptor。创建代理对象的具体方式不同,JDK动态代理是利用Proxy.newProxyInstance,传入的参数是(被代理对象所在类的类加载器,被代理对象所在类实现的接口,代理对象),而CGLIB是通过new Enhancer对象,而后为这个对象set(代理对象的回调方法),se(被代理对象所在的类)。
实际应用:在spring中,spring默认使用的是JDK动态代理,JDK动态代理要求被代理的对象的所在类必须实现接口,但CGLIB代理对被代理的对象不做要求。spring推荐使用的是JDK的动态代理。因为 spring推荐使用面向接口编程。