java两种代理

下文我们谈论关于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推荐使用面向接口编程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值