后端技术Java 杂谈Java后端必备

动态代理系列(二)JDK动态代理

2018-09-17  本文已影响1人  关捷

从第一讲静态代理我们知道,静态代理确实是能够增强现有逻辑的非常简单的一种方式。

请思考?

如果我增强的逻辑是相同的,并且需要增强的类的种类非常多,那么使用静态代理,会有什么问题?

问题是?

需要新增的代理类数目很多且手工编码,工作量巨大,有什么办法能够自动的生成类呢?。

答案呢?

动态代理。

什么又是动态代理呢?

首先它是代理,是通过间接的调用目标类,增强目标类。为什么叫动态,这个是相对而静态而言的,指的是代理类的生成方式。静态代理是需要一个个进行编码创建代理类,而动态代理,只需要写增强的逻辑,根据需要反射调用目标类方法,然后通过创建器就能自动的生成代理类。

如何实现?举个例子。

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动态代理的价值。

上一篇下一篇

猜你喜欢

热点阅读