关注点分离原则是现代应用程序框架(如 Spring 或 Hibernate)的主要方面之一。目的是将横切关注点(例如数据库访问、事务管理或安全检查)与功能需求的实现分开。实现关注点透明分离的一种可能解决方案是使用代理设计模式。代理是某种包装器,它控制对任何对象的接口的访问。因此,代理实现与包装对象相同的接口。通过使用代理模式,您可以在不更改对象本身的情况下扩展或更改对象的行为。
在 Java 中实现代理模式非常简单。自 1.3 版以来,所谓的 JDK 代理是 Java API 的一部分。您所需要的只是接口 InvocationHandler 和帮助类 Proxy。我们来看一个简单的例子。给定一个接口:
public interface Service {
public void foobar();
}
您可能希望在运行时监视其性能的接口的以下实现:
public class ServiceToBeMonitored implements Service {
@Override
public void foobar() {
try {
TimeUnit.MILLISECONDS.sleep(200);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
我们没有将性能测量代码直接写入服务实现中,而是通过使用代理模式来分离这个问题。因此我们实现了InvocationHandler接口:
public class PerformanceMonitor implements InvocationHandler {
private final Object proxiedInstance;
public PerformanceMonitor(Object proxiedInstance) {
this.proxiedInstance = proxiedInstance;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
long t0 = System.nanoTime();
Object result = method.invoke(proxiedInstance, args);
long t1 = System.nanoTime();
long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0);
System.out.println("Invocation of method " + method.getName() + "() took " + millis + " ms");
return result;
}
}
而已。现在我们已准备好创建代理。代理将方法调用委托给包装的对象。
Service service = new ServiceToBeMonitored();
PerformanceMonitor handler = new PerformanceMonitor(service);
Service proxy = (Service) Proxy.newProxyInstance(
service.getClass().getClassLoader(), new Class[]{ Service.class }, handler);
调用 proxy.foobar() 结果: Invocation of method foobar() took 201 ms