Design Pattern - Proxy

一般涉及三个角色:

使用代理(Proxy)的作用/意义:为真实角色提供一个代理以控制对该角色的访问。

实际使用场景

代理种类

代理模式,一般分为两种:

两者的区别在于:代理类是静态生成的还是动态生成的。

静态代理

静态代理中,代理类在编译前就写好。

design-pattern-proxy-1.png

一般通过两种方式实现:

// 此例中采用了抽象类
abstract public class Subject {
    abstract public void  request();
}

public class  RealSubject  extends  Subject  {
  public  RealSubject()  { }

  public void  request()  {
     System.out.println( " From real subject. " );
    }
}

public class  ProxySubject  extends  Subject  {
  private  Subject realSubject;
  public  ProxySubject(Subject realSubject)  {this.realSubject = realSubject }
  public void  request()  {
     preRequest();
     realSubject.request();  // 此处执行真实对象的request方法
     postRequest();
  }
  ...
}

// 客户端调用
RealSubject real = new RealSubject();
Subject sub = new  ProxySubject(real);
Sub.request();

问题:在静态代理中,一个RealSubject对应一个Proxy,大量使用这种代理模式,会使我们系统内的类的规模增大,并且不易维护。并且,Proxy的实际使用逻辑一般是:在调用某个方法前及方法后做一些额外的业务。如果这些额外的业务是一样的,比如写log,使用静态代理为每一个真实角色都创建一个对应的代理角色就会显得很多余。

design-pattern-proxy-2.png

解决:在运行状态中,需要代理的地方,根据Subject和RealSubject,动态地创建一个Proxy,用完之后就销毁。

动态代理

动态代理中,代理类是在运行时动态生成的。

参考以下代码,新建了一个代理类ProxySubjectA,与此类似,我们可以创建ProxySubjectB,ProxySubjectC,等等。它们的代码高度类似。为了简化,我们可以使用动态代理。

    public class ProxySubjectA implements SubjectA {
        private Subject realSubject;
        public  ProxySubject(Subject realSubject)  {
            this.realSubject = realSubject 
        }
        public void request() {
            preRequest();
            realSubject.request();
            postRequest();
        }
        ...
    }

那么这个动态代理是如何生成的呢?是使用了java.lang.reflect.Proxy下面的newProxyInstance方法创建得到的。

static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)

这里传入了三个参数

design-pattern-proxy-3.png

前两个参数RealSubject,Subject很好理解,在静态代理中也用到了,最后一个参数InvocationHandlerImpl,是动态代理独有的,它的作用是定义ProxySubject有哪些功能。然后在需要调用的地方通过Proxy.newProxyInstance(…)来动态创建ProxySubject类。

http://blog.csdn.net/luanlouis/article/details/24589193/

// Subject
public interface UserService {
    public abstract void add();
}

// RealSubject
public class UserServiceImpl implements UserService {
    public void add() {
        System.out.println("add");
    }
}

// InvocationHandlerImpl
public class MyInvocationHandler implements InvocationHandler {
    private Object target;
    public MyInvocationHandler(Object target) {
        super();
        this.target = target;
    }
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before");
        Object result = method.invoke(target, args);  // 调用真实对象的方法
        System.out.println("after");
        return result;
    }
    public Object getProxy() {  //  动态创建代理类
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                target.getClass().getInterfaces(), this);
    }
}

// 实际调用逻辑
public void testProxy() throws Throwable {
    UserService userService = new UserServiceImpl();
    MyInvocationHandler invocationHandler = new MyInvocationHandler(userService);
    UserService proxy = (UserService) invocationHandler.getProxy();
    proxy.add();
}

http://rejoy.iteye.com/blog/1627405

总结

静态代理的实现,我们涉及到创建三个类/接口:

然后在需要调用的地方直接创建ProxySubject类。

动态代理的实现,两个不变,新加了一个:

ProxySubject是通过Proxy.newProxyInstance(…)动态生成的。

Fork me on GitHub