Java 代理设计模式

Java 代理设计模式

为其他对象提供一种代理以控制对这个对象的访问。代理对象起到中介作用,可去掉功能服务或增加额外的服务

1、静态代理

在静态代理模式之下,我们显示地创建代理类,代理类持有被代理类的对象,实现与被代理类 的相同接口,并且增添相应的业务逻辑,以达到代理的效果

代理和被代理对象在代理之前是确定的,他们都实现相同的接口或者继承相同的抽象类

如何实现:创建一个接口,然后创建被代理的类实现该接口并且实现该接口中的抽象方法。之后再创建一个代理类,同时使其也实现这个接口。在代理类中持有一个被代理对象的引用,而后在代理类方法中调用该对象的方法

/**
* 服务接口
*/
public interface Service {

   /**
    * 服务
    */
   void doService(String name);

}

/**
* 服务员(被代理对象,下面称为目标对象)
*/
public class Waiter implements Service{

   @Override
   public void doService(String name) {
       System.out.println("正在服务"+name);
  }
}

/**
* 代理服务员
*/
public class ProxyWaiter implements Service{
   private Waiter waiter;//目标对象

   public ProxyWaiter(Waiter waiter) {
       this.waiter = waiter;
  }

   /**
    * 服务
    * @param name
    */
   @Override
   public void doService(String name) {
       System.out.println("欢迎光临");
       waiter.doService(name);
       System.out.println("欢迎下次光临");
  }
}

/**
*测试类
*/
public class Test {

   public static void main(String[] args) {
       //服务员(目标对象)
       Waiter waiter=new Waiter();
       //代理对象
       ProxyWaiter proxyWaiter=new ProxyWaiter(waiter);
       //服务
       proxyWaiter.doService("lsy");
  }

}

2、动态代理(重点)

2.1、jdk动态代理

利用反射机制在运行时创建代理类,代理对象必须实现某个接口

jdk动态代理具体步骤:

  • 通过实现 InvocationHandler 接口创建自己的调用处理器;

  • 通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类;

  • 通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;

  • 通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。

/**
* 服务接口
*/
public interface Service {

   /**
    * 服务
    */
   void doService(String name);

}

/**
* 服务员(被代理对象,下面称为目标对象)
*/
public class Waiter implements Service {

   /**
    * 服务
    * @param name
    */
   @Override
   public void doService(String name) {
       System.out.println("正在服务"+name);
  }
}

/**
* 处理目标对象类,实现InvocationHandler接口
*/
public class ProxyHandler implements InvocationHandler {
   private Object object;//目标对象(必须要实现一个接口)

   public ProxyHandler(Object object) {
       this.object = object;
  }

   /**
    * 处理主体:编写代理的逻辑代码增强
    * 参数一: proxy: 目标对象
    * 参数二: method:目标对象调用的方法
    * 参数三: args: 目标对象的方法的参数
    * 返回值:目标方法的返回值
    */
   @Override
   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
       Object rtValue=null;
       System.out.println("欢迎光临");
       rtValue=method.invoke(object,args);
       System.out.println("欢迎下次光临");
       return rtValue;
  }
}

/**
*测试类
*/
public class Test {

   public static void main(String[] args) {
       //服务员(目标对象)
       Waiter waiter=new Waiter();
       //代理目标对象
       ProxyHandler proxyHandler=new ProxyHandler(waiter);
       //得到代理后的目标对象(不能强转为接口的实现)
       Service service= (Service) Proxy.newProxyInstance(waiter.getClass().getClassLoader(),waiter.getClass().getInterfaces(),proxyHandler);
       //服务
       service.doService("lsy");
  }

}

参考资料:https://www.jianshu.com/p/9bcac608c714

2.2、cglib动态代理

通过cglib的动态代理它能够针对实现没有接口的目标类,进行动态代理

注意:要手动加载cglib的库文件

  • 实现原理

    • cglib它会生成目标类的子类实现,因此目标类作为父类注入,并且调用父类的方法

/**
* 服务员(被代理对象,下面称为目标对象)
*/
public class Waiter {

   /**
    * 服务
    */
   public void doService(){
       System.out.println("正在服务");
  }

}

/**
* 代理目标对象类
*/
public class MyMethodInterceptor implements MethodInterceptor {

   /**
    * 处理主体:编写代理的逻辑代码增强
    * 参数一: 0: 目标对象的引用
    * 参数二: method:目标对象调用的方法
    * 参数三: args: 目标对象的方法的参数
    * 参数四:当前执行方法的代理对象
    * 返回值:目标方法的返回值
    */
   @Override
   public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
       System.out.println("准备服务");
       //调用目标对象的方法
       //方式一
       //Object object=method.invoke(new Waiter(),objects);
       //方式二
       Object object=methodProxy.invokeSuper(o,objects);
       System.out.println("服务结束");
       return object;
  }
   /*
   *invoke方法调用的对象没有增强过,invokeSuper方法调用的对象已经是增强了的,所以会再走一遍 MyMethodInterceptor的     *interceptor方法,如果是个拦截器链条,就会重新在走一次拦截器链;
   */
}

/**
* 测试类
*/
public class Test {

   public static void main(String[] args) {
       //目标对象
       Waiter waiter=new Waiter();
       //创建Enhancer对象,类似于JDK动态代理的Proxy类,下一步就是设置几个参数
       Enhancer enhancer = new Enhancer();
       //注入目标对象类字节码文件
       enhancer.setSuperclass(Waiter.class);
       //设置回调函数
       enhancer.setCallback(new MyMethodInterceptor());
       //获取代理后的目标对象
       Waiter w=(Waiter) enhancer.create();
       //服务
       w.doService();
  }

}

参考资料:https://www.cnblogs.com/wyq1995/p/10945034.html

记得快乐
原文地址:https://www.cnblogs.com/Y-wee/p/13523685.html