代理模式
他是在不改变原始类(被代理类)代码情况下,通过引入代理类来给原始添加功能。
动态代理
我们不需要事先为每个原始类编写代理类,然后在运行的时候,动态的创建原始类的代理类,然后在系统中使用代理类代替原始类。Java动态代理底层依赖java的反射语法。
例子:创建一个接口运行时间计数器。
原始方式:
public class MetricsCollectorProxy {
//计数统计类
private MetricsCollector collector;
public MetricsCollectorProxy() {
this.collector = new MetricsCollector();
}
public Object createProxy(Object proxiedObject) {
Class<?>[] interfaces = proxiedObject.getClass().getInterfaces();
DynamicProxyHandler handler = new DynamicProxyHandler(proxiedObject);
return Proxy.newProxyInstance(proxiedObject.getClass().getClassLoader(), interfaces, handler);
}
private class DynamicProxyHandler implements InvocationHandler {
private Object proxiedObject;
public DynamicProxyHandler(Object proxiedObject) {
this.proxiedObject = proxiedObject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
long start = System.currentTimeMillis();
Object result = method.invoke(proxiedObject, args);
long end = System.currentTimeMillis();
long run = end - start;
String apiName = proxiedObject.getClass().getName() + ":" + method.getName();
RequestInfo info = new RequestInfo(apiName, run);
collector.recordRequest(info);
return result;
}
}
}
//使用
MetricsCollectorProxy proxy = new MetricsCollectorProxy();
IVersionController controller = (IVersionController) proxy.createProxy(new VersionController());
实际上Spring AOP底层就是就是基于动态代理。 springboot切面AOP简单使用 - 掘金 (juejin.cn)
使用
代理模式使用场景很多,比如业务系统中开发非功能性需求,比如监控、统计、鉴权、限流、事务、幂等、日志等。除此之外还可用在RPC、缓存等应用场景中。