为其他对象提供一种代理以控制对这个对象的访问,避免直接访问对象带来的问题,比如需要事务控制,需要异步,在访问一个类时做一些控制,比如Spring的AOP就是依赖代理实现,可以不嵌入原本业务代码,动态添加功能。
直接看代码吧
真实对象:
interface Subject {
/**
* 对象请求
*/
void request();
}
@Log4j2
class RealSubject implements Subject {
@Override
public void request() {
log.info("真实对象请求");
}
}
代理对象需要持有一个真实对象:
@Log4j2
@Data
class StaticProxy implements Subject {
private Subject realSubject;
@Override
public void request() {
log.info("静态代理对象请求");
realSubject.request();
}
}
通过代理对象访问真实对象:
Subject subject = new RealSubject();
log.info("没有代理");
subject.request();
log.info("有代理");
StaticProxy staticProxy = new StaticProxy();
staticProxy.setRealSubject(subject);
staticProxy.request();
结果:
15:37:26.319 [main] INFO com.learn.putc.designpatterns.structure.proxy.ProxyPattern - 没有代理
15:37:26.327 [main] INFO com.learn.putc.designpatterns.structure.proxy.RealSubject - 真实对象请求
15:37:26.328 [main] INFO com.learn.putc.designpatterns.structure.proxy.ProxyPattern - 有代理
15:37:26.329 [main] INFO com.learn.putc.designpatterns.structure.proxy.StaticProxy - 静态代理对象请求
15:37:26.329 [main] INFO com.learn.putc.designpatterns.structure.proxy.RealSubject - 真实对象请求
在执行真实对象请求前后 我们都可以做些其它事,比如日志打印、统计耗时、加事务控制
但是这种代理,需要为每一种真实对象都建立个代理对象,也称静态代理
显然这样很麻烦,有没有一种方式可以动态的创建代理对象呢?
基于JDK的动态代理:
@Log4j2
@Data
class DynamicProxy<T> implements InvocationHandler {
private T target;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
log.info("动态代理 前");
Object result = method.invoke(target, args);
log.info("动态代理 后");
return result;
}
}
调用:
log.info("动态代理实现");
DynamicProxy<Subject> subjectDynamicProxy = new DynamicProxy<>();
subjectDynamicProxy.setTarget(subject);
Subject subjectDynamicProxy0 =
(Subject)Proxy.newProxyInstance(
Subject.class.getClassLoader()
, new Class<?>[]{Subject.class}
, subjectDynamicProxy);
subjectDynamicProxy0.request();
这样就可以灵活的为任何对象添加代理啦