本帖最后由 吉山小学生 于 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 以上就是对动态代理的基本描述。下次有时间在进一步介绍动态代理的技术。
|