zoukankan      html  css  js  c++  java
  • 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

    记得快乐
  • 相关阅读:
    zoj3430Detect the Virus(ac自动机)
    zoj3494BCD Code(ac自动机+数位dp)
    hdu3247Resource Archiver(ac自动机+spfa)
    hdu3341Lost's revenge(ac自动机+dp)
    hdu4511小明系列故事——女友的考验(ac自动机+最短路)
    hdu4758Walk Through Squares(ac自动机+dp)
    数论一
    母函数专题
    KMP专题
    3级算法题
  • 原文地址:https://www.cnblogs.com/Y-wee/p/13523685.html
Copyright © 2011-2022 走看看