一、代理模式
代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
代理模式一般涉及到的角色有:
(1)抽象角色:声明真实对象和代理对象的共同接口;
(2)代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。
(3)真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。
二、静态代理
UML图:转自http://www.cnblogs.com/machine/archive/2013/02/21/2921345.html
客户实际需要调用的是RealSubject类的方法,现在用 ProxySubject来代理 RealSubject类,同样达到目的。
但是:
(1)如果代理类要在真实角色中的每个方法执行前后进行同样的操作,岂不是会产生大量重复代码?
(2)静态代理中真实对象对应一个代理角色,如果大量使用,会导致类的急剧膨胀;此外,如果事先并不知道真实角色,该如何使用编写代理类?
所以引入——
二、动态代理
代理类在程序运行时创建的代理方式被成为动态代理。也就是说,这种情况下,代理类并不是在Java代码中定义的,而是在运行时根据我们在Java代码中的“指示”动态生成的。相比于静态代理,动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类的函数。
UML图:转自http://www.cnblogs.com/machine/archive/2013/02/21/2921345.html
主要关注:
(1)InvocationHandler接口
在使用动态代理时,我们需要定义一个位于代理类与委托类之间的中介类,这个中介类被要求实现InvocationHandler接口,这个接口的定义如下:
public interface InvocationHandler { Object invoke(Object proxy, Method method, Object[] args); }
从InvocationHandler这个名称我们就可以知道,实现了这个接口的中介类用做“调用处理器”。当我们调用代理类对象的方法时,这个“调用”会转送到invoke方法中,代理类对象作为proxy参数传入,参数method标识了我们具体调用的是代理类的哪个方法,args为这个方法的参数。这样一来,我们对代理类中的所有方法的调用都会变为对invoke的调用,这样我们可以在invoke方法中添加统一的处理逻辑(也可以根据method参数对不同的代理类方法做不同的处理)。
(2)Proxy类:完成代理操作的,可为一个/多个接口动态地生成实现类,此类提供了下面的方法,用于获取一个代理类实例。
这个代理类实现了我们指定的接口并且会把方法调用分发到指定的调用处理器
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
三、一个简单的demo用于理解java代理机制
package com.yyj.dynProvxy;
//静态代理:一个代理只为一个接口服务
//动态代理:一个代理可为多个接口服务,除了调用的方法不同,其他操作均相同
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.lang.reflect.Method;
/**
* Created by GraceYang on 2017/3/27.
*/
interface Person{
public String introduce(String name,int age);
public String havelunch(String food);
}
class RealPerson implements Person{
@Override
public String introduce(String name, int age) {
return "姓名:"+name+" 年龄:"+age;
}
public String havelunch(String food){
return "午饭:"+food;
}
}
//静态代理
class ProxyPerson implements Person{
private Person person;
public ProxyPerson(Person person){
this.person=person;
}
@Override
public String introduce(String name, int age) {
System.out.println("I will do something in static proxy");
return this.person.introduce(name,age);
}
public String havelunch(String food){
System.out.println("I will do something in static proxy");
return this.person.havelunch(food);
}
}
//动态代理
class PersonInvocationHandler implements InvocationHandler{
private Object obj; //真实主题
//bind方法:根据传来的object对象返回相应的实例
public Object bind(Object obj){//绑定真实操作主题
this.obj=obj;//真实主题类
//取得代理对象;return newInstance(cons, ih)
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),this);
}
//动态调用方法
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable{
System.out.println("I will do something in dynamic proxy");
Object temp=method.invoke(this.obj,args);//动态调用方法,传入真实对象和参数
return temp;//返回方法的返回信息
}
}
public class DynaProxydemo1 {
public static void main(String args[]){
Person person=new ProxyPerson(new RealPerson());
System.out.println(person.introduce("杨鼎",23));
System.out.println(person.havelunch("大鸡腿"));
//动态代理,bind方法根据new RealPerson()返回一个object实例
Person person2=(Person)new PersonInvocationHandler().bind(new RealPerson());
//当我们调用代理类对象的方法时,这个“调用”会转送到invoke方法中
System.out.println(person2.introduce("杨鼎",23));
System.out.println(person2.havelunch("小鸡腿"));
}
}
运行结果: