A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

本帖最后由 吉山小学生 于 2018-3-8 19:09 编辑

代理概述
  生活中代理模式处处可见,例如,厂商和代理商,房东和房屋中介,当事人和律师等等这些都是代理模式的具体体现。我们可以把厂商、房东、当事人成为委托人,把代理商、房屋中介、律师成为代理人。上述的委托人和代理人的关系的共同特点就是----代理人替委托人去执行了某些行为,并且增强了这些行为。比如,厂商没有自己去销售自己的产品,而是让自己的代理商去销售,并且代理的销售能力更加强大。房东没有自己去出租自己的房屋,而是让房产中介去出租,并且房屋中介可以更快的把房子出租出去。这就是代理模式。
  编程中代理模式跟现实生活中的一样。就是使用代理对象去执行委托对象的方法,并增强委托对象的方法。代理模式主要有三个角色:
  • 公共接口:代理类和委托类共同实现的接口。该接口声明了代理类要代理委托类执行那些方法。也称抽象角色
  • 委托类:真正实现业务逻辑的类,也称真实角色。
  • 代理类:替代委托类去执行抽象角色中定义的方法的类。在代理类中含有对真实角色的引用。
动态代理
  首先在动态代理中,有两个重要的引用类型,这两者是我们理解动态代理的关键。
  • Proxy(类)
    该类的作用就是动态的生成代理类和创建代理对象。创建代理类和代理实例常用的方法static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) 。
    • 返回值为代理类实例,其中方法的参数指定了代理类的加载器,代理类要实现的接口,代理实例对代理方法的调用处理将会指派给InvocationHandle 的实例。
    • load 参数指定了动态生成的代理类的加载器,对代理类的加载我们会使用委托类的加载器。
    • interfaces 指定代理类要实现的接口,也就是和委托类共同接口。
    • h 代理实例对代理接口上的方法的调用进行处理是没有办法控制,所以我们要把方法的调用处理委托给InvocationHandle 实例,在InvocationHandle 实例的invoke 方法,我们可以获得代理方法调用的相关信息
  • InvocationHandle(接口)
    由于代理类及其实例是在运行时生成且内置在JDK中。我们没有办法对代理类代理的方法进行控制。但是代理实例会将代理方法的调用处理继续委托给实现了InvocationHandle接口的实例。也就是每个代理实例都关联着一个用于代理方法调用处理的实例,当代理实例对代理方法进行调用时,将对方法的调用编码并指派给它的调用处理实例invoke 方法。在接口InvocationHandle 中就一个方法Object invoke(Object proxy, Method method, Object[] args) 。
    • proxy ---代理的实例
    • method ---代理实例调用的代理方法的Method实例。
    • args ---代理实例调用代理方法时传入的参数数组。如果代理方法没有参数,则为null 。

  上面对动态代理技术中的两个重要的数据类型做了描述,下面我们使用代码对动态代进一步理解。首先要定义一个接口来声明代理方法。
  
[Java] 纯文本查看 复制代码
public interface ProxyMethod {

    public void code();
    public void codeWith(String str);

   }

接下来,我们定义一个委托类client ,并实现上面的代理方法。
[Java] 纯文本查看 复制代码
public class Client impliment ProxyMethod{
    @override
    public void code(){

        System.out.println("I love code");

    }
     @override
    public void codeWith(String str){


        System.out.println("I am coding with " + str);

    }

  }

然后我需定义一个用于处理代理方法调用的类,该类必须实现接口InvocationHandle 。
  
[Java] 纯文本查看 复制代码
public class InvokeHandler impliment InvocationHandle {
      //需要代理的委托类实例
    private ProxyMethod clientInstance;

    //构造方法
    public InvokeHandler (ProxyMethod clientInstance){
        this.clientInstance = clientInstance;
    }

    @override
    public Object invoke(Object object, Method method, Object[] args) throws Throwable{
        //在委托类实例调用方法之前,我们可以添加自己的操作
        System.out.println("before coding");

        //委托类实例自己调用方法
        method.invoke(clientInstance,args);

        //在委托类实例调用方法之后,添加自己的操作
        System.out.println("after coding");

        return null;

    }
  }
最后我们定义一个测试类,去测试一下效果
   
[Java] 纯文本查看 复制代码
public class Test {

        public static void main (String[] args){

            //创建一个委托类对象
            Client ct = new Client();

            //创建一个方法调用处理类实例
            InvokeHandler handler = new InvokeHandler(ct);

            //动态创建一个代理实例
                ProxyMethod proxyInstance = (ProxyMethod)Proxy.newProxyInstance(ct.getClass().getClassLoader(), ct
                .getClass().getInterfaces(), handler);

            //代理实例调用代理方法
            proxyInstance.code();

        }

    }
让我们来看一下控制台的输出:
   
[Java] 纯文本查看 复制代码
 before code
 I love code
 after code
以上就是对动态代理的基本描述。下次有时间在进一步介绍动态代理的技术。

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马