代理模式

背景

代理模式中,代理类与主体类实现同样的接口,代理类持有实体类的引用,并接受客户端对代理类中实体引用部分的外部注入,并代理实体类的功能。

按照代理类的产生方式,如果运行期之前就静态的存在那就是静态代理,如果是运行时产生的就是动态代理。
代理模式的类图如下
图1: 动态代理类图

静态代理

一个代码示例

// 1. 定义接口
interface Subject {
    String action();
}

// 2. 定义主体类
public class RealSubject implements Subject {
    @Override
    public String action() {
        System.out.println("action in RealSubject");
        return "action done";
    }
}

// 3. 定义静态代理类 它持有一个主体类的引用
public class ProxySubject implements Subject {
    private RealSubject realSubject;
    public ProxySubject(Subject realSubject) {
        this.realSubject = realSubject;
    }

    @Override
    public String action() {
        System.out.println("do sth before RealSubject action");
        String result = realSubject.action();
        System.out.println("do sth after RealSubject action");
        // 返回值仍要主体的返回值
        return result;
    }
}

// 4. 在客户端注入实体并使用
public class Client {
    public static void main(String[] args) {
        Subject realSubject = new RealSubject();
        ProxySubject proxySubject = new ProxySubject(realSubject);
        proxySubject.action();
    }
}

// 5. 运行后输出结果
do sth before RealSubject action
action in RealSubject
do sth after RealSubject action

动态代理

动态代理也遵循上面的类图,和静态代理相比,有以下几点不同之处

  1. 代理类ProxySubject是在运行时动态生成的,而编译期是不存在的
  2. 代理类与主体类的代理关系是动态注入的(ProxySubject持有RealSubject的引用)
  3. 代理类对主体类的方法调用也是动态的

代理类的动态生成,代理类与主体类的关系建立以及对主体类的代理调用,都用到了两个关键类,即Proxy和InvocationHandler

Proxy类提供了动态生成代理类的方法并持有InvocationHandler接口的引用,所有生成的代理类都是Proxy的子类.

public static Object newProxyInstance(ClassLoader loader, Class[] interfaces,
                                      InvocationHandler h) throws IllegalArgumentException

InvocationHandler接口包含一个invoke方法,让实现InvocationHandler接口的类去具体实现,在实现中通过持有被代理类实体(RealSubject),并通过反射,去调用对应的实体方法。

参考文章

动态代理三部曲(一):动态代理模式及实现原理

你可能感兴趣的:(代理模式)