一 代理模式

定义:在拜访指标对象的时候,提供一种间接拜访的办法,通过代理对象去拜访指标对象,达到客户端的目标。

益处:爱护指标对象;在指标对象的行为根底上,代理对象能够减少本人的解决,使得同一个指标对象能够满足不同的客户端的目标。

代理模式的模型:

波及三个角色:

RealSubject:指标对象,也是真正要做事件的人。

Proxy:代理对象,持有对指标对象的援用,裸露给客户端,通过操作指标对象来实现客户端的目标。并且,代理对象能够在操作指标对象的前后做一些自定义的行为,灵便扩大了指标对象。

Subject:指标对象和代理对象的形象,以便在任何应用指标对象的中央都能够应用代理对象。Subject能够是一个接口也能够是一个抽象类。

二 动态代理

以最简略的模式实现上述模型

public interface Subject {    void doRequst();}public class RealSubject implements Subject {    @Override    public void doRequst() {        System.out.println("it's the thing i really want to do");    }}public class Proxy implements Subject {    private Subject subject;    public Proxy(Subject subject){        this.subject = subject;    }    @Override    public void doRequst() {        System.out.println("before do the real thing");        subject.doRequst();        System.out.println("after do the real thing");    }}public class Client {    public static void main(String[] args) {        Proxy proxy = new Proxy(new RealSubject());        proxy.doRequst();    }}/**before do the real thingit's the thing i really want to doafter do the real thing**/

这种实现形式即常说的动态代理,有几个方面的束缚:

1 代理对象和指标对象须要实现独特的接口,接口有变动,指标对象和代理对象都须要保护。

2 想要代理其余的指标对象,须要新增代理类。

三 动静代理

先看java实现动静代理的几个次要角色

1  Proxy :java.lang.reflect.Proxy,jdk api提供的代理类的主类,该类提供办法动静生成代理类,生成的时候须要指定一组接口(即代理类和指标对象要实现哪些接口)

public static Object newProxyInstance(ClassLoader var0, Class<?>[] var1, final InvocationHandler var2) throws IllegalArgumentException /**提供了这个静态方法用于动静生成代理类var0:   指标对象的类加载器var1:  代理类要实现哪些接口,即指标对象实现的接口var2:  处理器,代理类具体要做什么写在处理器中**/

2 InvocationHandler :java.lang.reflect.InvocationHandler

/**@param  proxy the proxy instance that the method was invoked on代理对象,执行invoke的时候其实是在替这个proxy执行@param  method the {@code Method} instance corresponding tothe interface method invoked on the proxy instance.  The declaringclass of the {@code Method} object will be the interface thatthe method was declared in, which may be a superinterface of theproxy interface that the proxy class inherits the method through.指标对象要执行的办法@param  args an array of objects containing the values of thearguments passed in the method invocation on the proxy instance,or {@code null} if interface method takes no arguments.Arguments of primitive types are wrapped in instances of theappropriate primitive wrapper class, such as{@code java.lang.Integer} or {@code java.lang.Boolean}.执行办法须要的参数**/ public Object invoke(Object proxy, Method method, Object[] args)    throws Throwable 

java动静代理实例

public interface Subject {    void doRequest();}public class RealSubject1 implements Subject {    @Override    public void doRequest() {        System.out.println("RealSubject1 want to sing");    }}public class RealSubject2 implements Subject {    @Override    public void doRequest() {        System.out.println("RealSubject2 want to dance");    }}public class RealInvocationHandler implements InvocationHandler {    private Object subject;    public RealInvocationHandler(Object subject){        this.subject = subject;    }    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        System.out.println("before process");        Object result = method.invoke(subject,args);        System.out.println("after process");        return result;    }}public class Client {    public static void main(String[] args) {        Subject realSubject1 = new RealSubject1();        InvocationHandler handler1 = new RealInvocationHandler(realSubject1);        Subject subject1 = (Subject) Proxy.newProxyInstance(realSubject1.getClass().getClassLoader(),realSubject1.getClass().getInterfaces(),handler1);        subject1.doRequest();        System.out.println("-----------------------");        Subject realSubject2 = new RealSubject2();        InvocationHandler handler2 = new RealInvocationHandler(realSubject2);        Subject subject2 = (Subject)Proxy.newProxyInstance(realSubject2.getClass().getClassLoader(),realSubject2.getClass().getInterfaces(),handler2);        subject2.doRequest();    }}/**before processRealSubject1 want to singafter process-----------------------before processRealSubject2 want to danceafter process**/

与动态代理做个比拟:

不须要挨个写代理类,想代理其余的,动静new一个代理类

相干源码解析

Proxy.newProxyInstance生成的代理具备什么以及为什么能够转换成指标对象

protected InvocationHandler h;  public static Object newProxyInstance(ClassLoader loader,                                      Class<?>[] interfaces,                                      InvocationHandler h)    throws IllegalArgumentException{    // 校验handler    if (h == null) {        throw new NullPointerException();    }    final Class<?>[] intfs = interfaces.clone();    final SecurityManager sm = System.getSecurityManager();    if (sm != null) {        checkProxyAccess(Reflection.getCallerClass(), loader, intfs);    }    /*     * Proxy保护了一个proxyClassCache,如果想要的代理类曾经有实现了指定接口的loader定义好了,间接返回cache的备份     * 否则,通过ProxyClassFactory 生成一个代理类,实现指定的intfs     */    Class<?> cl = getProxyClass0(loader, intfs);    /*     * Invoke its constructor with the designated invocation handler.     */    try {        //获取构造函数,将传进来的h赋给proxy外部持有的Invokerhanler对象        final Constructor<?> cons = cl.getConstructor(constructorParams);        final InvocationHandler ih = h;        if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) {            // create proxy instance with doPrivilege as the proxy class may            // implement non-public interfaces that requires a special permission            return AccessController.doPrivileged(new PrivilegedAction<Object>() {                public Object run() {                    return newInstance(cons, ih);                }            });        } else {            return newInstance(cons, ih);        }    } catch (NoSuchMethodException e) {        throw new InternalError(e.toString());    }}

所以,Proxy生成的代理对象具备一个invokehandler对象的援用;并且实现了指标对象实现的接口,因为能够转换为指标对象的形象

InvokeHandler为什么能够实现指标对象办法的执行

如上述例子中指标对象RealSubject1要执行doRequest办法,Proxy生成的代理类也会实现这个办法,大略如下:

 public final void doRequest()     {        //这个会调用invokehandler的invoke办法,这里的h即是父类Proxy的h,通过newProxyInstance传进来的        try {            this.h.invoke(this, m3, null);            return;        } catch (RuntimeException localRuntimeException) {            throw localRuntimeException;        } catch (Throwable localThrowable) {            throw new UndeclaredThrowableException(localThrowable);        }     }

有了InvocationHandler 能够使Proxy从具体的代码逻辑抽离进去,更不便对立的生成代理类。

后续todo:

Proxy生成的代理对象的具体分析

method.invoke具体做了什么