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

    记得快乐
  • 相关阅读:
    New version of VS2005 extensions for SharePoint 3.0
    QuickPart : 用户控件包装器 for SharePoint Server 2007
    随想
    发布 SharePoint Server 2007 Starter Page
    如何在SharePoint Server中整合其他应用系统?
    Office SharePoint Server 2007 中文180天评估版到货!
    RMS 1.0 SP2
    SharePoint Server 2007 Web内容管理中的几个关键概念
    如何为已存在的SharePoint站点启用SSL
    Some update information about Office 2007
  • 原文地址:https://www.cnblogs.com/Y-wee/p/13523685.html
Copyright © 2011-2022 走看看