从第一讲静态代理我们知道,静态代理确实是能够增强现有逻辑的非常简单的一种方式。
请思考?
如果我增强的逻辑是相同的,并且需要增强的类的种类非常多,那么使用静态代理,会有什么问题?
问题是?
需要新增的代理类数目很多且手工编码,工作量巨大,有什么办法能够自动的生成类呢?。
答案呢?
动态代理。
什么又是动态代理呢?
首先它是代理,是通过间接的调用目标类,增强目标类。为什么叫动态,这个是相对而静态而言的,指的是代理类的生成方式。静态代理是需要一个个进行编码创建代理类,而动态代理,只需要写增强的逻辑,根据需要反射调用目标类方法,然后通过创建器就能自动的生成代理类。
如何实现?举个例子。
public class ClientObj {
public static void main(String[] args) {
TargetObj targetObj = new TargetObj();
TargetObjIntf proxyObj = getProxy(targetObj);
proxyObj.doSomeThing();
}
//生成代理类
private static <T> T getProxy(T t) {
return (T) Proxy.newProxyInstance(t.getClass().getClassLoader(),
t.getClass().getInterfaces(), new ProxyObjHandler(t));
}
static class TargetObj implements TargetObjIntf {
@Override
public void doSomeThing() {
System.out.println("目标类:doSomeThing()");
}
}
//目标类接口
interface TargetObjIntf {
void doSomeThing();
}
//统一的代理逻辑
static class ProxyObjHandler implements InvocationHandler {
private Object targetObj;
public ProxyObjHandler(Object targetObj) {
this.targetObj = targetObj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("这里是代理类增强逻辑,下面继续反射执行目标类的方法!");
return method.invoke(targetObj, args);
}
}
}
执行结果:
这里是代理类增强逻辑,下面继续反射执行目标类的方法!
目标类:doSomeThing()
可以看出,增强逻辑执行了,并且如果不做控制,目标类和代理类所有相同名字的方法,都会执行这段逻辑,包括equals,toString等Object的通用方法。
所以我们需要在增强代码中通过条件来控制,是否真正的需要继续增强逻辑,可以通过注解标记、正则表达式或者方法名字等方式进行筛选,而这正是Spring切面表达式的左右。
上面代码,只是简单的打印一句话,实际中,我们可以记录日志、统计方法执行的耗时、业务成功率、记录入参等等操作。
总结下:能够对通用的逻辑进行统一的处理,这就是JDK动态代理的价值。
网友评论