JDK的Proxy动态代理模式和CGLIB动态代理模式的区别和共同点

首先我们来谈谈联众代理模式的不同之处:

《1》代理类不同点:

(1)Proxy的代理类的创建是通过工具类或者工厂类自动创建的,

   我们只需要调用Proxy.newProxyInstance(Loader,interfaces,h);正确的传入相应的参数,就可以得到饿哦们想要的目标类的代理类,这里对这三个参数做一下简单的介绍:Loader是目标类的类加载器,Interfaces是目标类实现的所有接口,h,是委托类对象。代码如下:

//动态生成代理对象
  ISomeService someServiceImpl = (ISomeService) Proxy.newProxyInstance(
    //目标类的类加载器 、

target.getClass().getClassLoader(),

    //目标类实现的所有接口
    target.getClass().getInterfaces(),
    
    //代理类的委托对象
    new ServiceProxyEntrust(target));

(1)Cglib的代理模式中,并没有提供现成的工具或者工厂 类让我们直接得到代理类,需要我们程序员手工定义类和方法来创建我们所需要的代理类,一般我个人喜欢把代理类的名字定义成“cglibProxy”,方法签名定义成“newProxyInstance“,

CglibProxy.newProxyInstance(target.getClass(),mi);

target是我们的目标类,mi是我们的委托类对象。我们手工定义的工厂类的需要实现这个newProxyInstance()方法,并且在这个方法的内部,我们需要借助增强器Enhancer来为我们的代理类指定目标类,并且让委托类和目标类发生联系,具体的代码实现如下:

package com.abc.utils;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
//手工编写的工具类,用于创建我们的代理对象
public class CglibProxy {
 
 //创建代理对象的过程中,我们需要借助一个类
 //target:是我们的目标类
 //mi:是我们的委托类对象
 public static Object newProxyInstance(Class<?> target, MethodInterceptor mi) {
  //增强器
  Enhancer enhancer = new Enhancer();
  
  //指定父类,即指定目标类
  enhancer.setSuperclass(target);
  
  //指定回调对象,即指定代理类
  //把目标类和委托类联系在了一起
  enhancer.setCallback(mi);
  
  //创建并且返回代理对象
  return enhancer.create();
 }
}

通过这种方法,Cglib也可以一般性的创建代理类,但是我们之前说过,我们需要个性化的增强目标类,所以我们还应该让这个目标类变得不一般,这就涉及到我们要说的第二点的不同,

《2》委托类的不同

(2)Proxy 的委托类需要实现InvocationHandler接口,该接口只有一个方法,我们需要重写这个方法,

publci Object invoke(Object proxy,Method method,Object[] args);该方法的功能就是通过植入交叉逻辑代码。来达到个性化增强目标类的目的。(proxy是代理对象,method,是目标方法,args是目标方法的参数)代码如下:

/**
  * proxy:代理对象
  * method:目标方法
  * args:目标方法的参数
  */
 @Override
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  //植入交叉逻辑
  SystemUtil.doTx();
  //通过反射执行目标方法
  Object result = method.invoke(target, args);
  //植入交叉逻辑
  SystemUtil.doLog();
  return result;
 }

(2)Cglib的委托类需要实现的接口是MethodInterceptor,然后需要重写该接口中的intercept() 方法,代码如下:

/**
  * obj:代理对象
  * method:目标方法
  * args:目标方法的参数
  * proxy:目标方法的代理对象
  */
 
 @Override
 public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
  //植入交叉逻辑
  SystemUtil.doTx();
  //通过反射执行目标方法
  Object result = method.invoke(target, args);
  //植入交叉逻辑
  SystemUtil.doLog();
  return result;

==================================================

小结:二者的不同之处在于

(1)Proxy的代理类是有工具类或者工厂类动态的生成(我们只需要调用相应的方法,然后正确的传入参数即可,具体的生成过程可以通过debug模式查看)

Cglib是没有提供相应的工具类,需要程序员手工编写,

(2)二者的委托类实现的接口不同,所以重写的的接口也不同

(3)Proxy 动态代理要求目标类必须是要实现接口的类,而Cglib的目标类可以不用实现接口(当然了实现了接口的目标类也同样可以适用,用法和没有实现接口的类似),但是Cglib的目标类是不能被final所修饰的,且必须提供无参的构造器(因为Cglib的代理类其实是目标类的子类)

============================

相同点:

(1)二者都可以在不修改目标类的源码的情况下,达到个性化增强目标类的业务逻辑功能的目的。

(2)二者的委托类虽然实现的接口和方法不同,但是这两个重写的方法的功能相同,都是通过在目标方法的前后执行交叉代码逻辑(或者是系统及服务)来达到增加目标方法的作用。



猜你喜欢

转载自blog.csdn.net/dawiebazhanlang/article/details/80953906