关注分离原则是现代应用程序框架(如 Spring 或 Hibernate)的主要方面之一。目的是将横切关注点(例如数据库访问、事务管理或安全检查)与功能需求的实现分开。实现关注点透明分离的一种可能解决方案是使用代理设计模式。代理是某种包装器,它控制对任何对象的接口的访问。因此,代理实现与包装对象相同的接口。通过使用代理模式,您可以在不更改对象本身的情况下扩展或更改对象的行为。
    在 Java 中实现代理模式非常简单。自 1.3 版以来,所谓的 JDK 代理是 Java API 的一部分。您所需要的只是接口 InvocationHandler 和帮助类 Proxy。我们来看一个简单的例子。给定一个接口:

    1. public interface Service {
    2. public void foobar();
    3. }

    您可能希望在运行时监视其性能的接口的以下实现:

    1. public class ServiceToBeMonitored implements Service {
    2. @Override
    3. public void foobar() {
    4. try {
    5. TimeUnit.MILLISECONDS.sleep(200);
    6. } catch (InterruptedException e) {
    7. throw new RuntimeException(e);
    8. }
    9. }
    10. }

    我们没有将性能测量代码直接写入服务实现中,而是通过使用代理模式来分离这个问题。因此我们实现了InvocationHandler接口:

    1. public class PerformanceMonitor implements InvocationHandler {
    2. private final Object proxiedInstance;
    3. public PerformanceMonitor(Object proxiedInstance) {
    4. this.proxiedInstance = proxiedInstance;
    5. }
    6. @Override
    7. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    8. long t0 = System.nanoTime();
    9. Object result = method.invoke(proxiedInstance, args);
    10. long t1 = System.nanoTime();
    11. long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0);
    12. System.out.println("Invocation of method " + method.getName() + "() took " + millis + " ms");
    13. return result;
    14. }
    15. }

    而已。现在我们已准备好创建代理。代理将方法调用委托给包装的对象。

    1. Service service = new ServiceToBeMonitored();
    2. PerformanceMonitor handler = new PerformanceMonitor(service);
    3. Service proxy = (Service) Proxy.newProxyInstance(
    4. service.getClass().getClassLoader(), new Class[]{ Service.class }, handler);

    调用 proxy.foobar() 结果: Invocation of method foobar() took 201 ms