一、简介
JdkDynamicAopProxy 代理类是spring 默认的JDK动态的代理类实现。它实现了Java 动态代理接口InvocationHandler接口和Spring定义的AopProxy接口。AopProxy定义了返回代理的对象。
二、阅读
public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException { Assert.notNull(config, "AdvisedSupport must not be null"); if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) { throw new AopConfigException("No advisors and no TargetSource specified"); } this.advised = config; }
从其构造函数来看,该类的入参是AdvisedSupport,并把入参设置到成员变量中。其中AdvisedSupport类是Aop代理的配置管理类,里面包括了代理的对象和被代理对象需要织入的通知Advice.
从该类实现了AopProxy接口,那么久可以返回代理的对象,其实现如下:
@Override public Object getProxy(@Nullable ClassLoader classLoader) { if (logger.isTraceEnabled()) { logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource()); } Class>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true); findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); }
首先从AopProxyUtils.completeProxiedInterfaces工具方法得到需要代理的接口,接着通过findDefinedEqualsAndHashCodeMethods私有方法判断这些需要的代理接口proxiedInterfaces是否重新定义了equals和hashcode方法,并把接口记录到this.equalsDefined 和 this.hashCodeDefined成员变量中。最后核心其实是通过Java的动态代理类Proxy 产生一个代理对象。所以每调用一次getProxy都会产生新的一个代理对象。
接着我们需要看下的就是InvocationHandler接口的invoke方法是如何实现的。注入和原理如下:
@Override @Nullable public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object oldProxy = null; boolean setProxyContext = false; // 通过this.advised得到代理的目标类, TargetSource targetSource = this.advised.targetSource; Object target = null; try { // 如何代理接口没有定义equals方法,则调用JdkDynamicAopProxy的重写的equals方法 if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { // The target does not implement the equals(Object) method itself. return equals(args[0]); } // 如何代理接口没有定义equals方法,则调用JdkDynamicAopProxy的重写的equals方法 else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { // The target does not implement the hashCode() method itself. return hashCode(); } //如果该方法申明类是DecoratingProxy,则直接最终的被代理类的类Class else if (method.getDeclaringClass() == DecoratingProxy.class) { // There is only getDecoratedClass() declared -> dispatch to proxy config. return AopProxyUtils.ultimateTargetClass(this.advised); } //如果目标对象是Advice类型,则直接使用反射进行调用 //opaque-->标记是否需要阻止通过该配置创建的代理对象转换为Advised类型,默认值为false,表示代理对象可以被转换为Advised类型 else if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) { // Service invocations on ProxyConfig with the proxy config... return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); } Object retVal; // 看是否需要暴露代理对象,如果需要放到threadLocal上 if (this.advised.exposeProxy) { // Make invocation available if necessary. oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } // Get as late as possible to minimize the time we "own" the target, // in case it comes from a pool. target = targetSource.getTarget(); Class> targetClass = (target != null ? target.getClass() : null); // 得到该调用方法的拦截链 List
从上面我们知道有几个特殊的接口,当方法的代理类是DecoratingProxy,或者是Advised都做了特殊的处理。原因在于在创建JdkDynamicAopProxy 对象是,有Class>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true); 这么一句语句。它返回的代理接口就可能包括DecortingProxy 和Advised。具体如下:
static Class>[] completeProxiedInterfaces(AdvisedSupport advised, boolean decoratingProxy) { Class>[] specifiedInterfaces = advised.getProxiedInterfaces(); // 首先得到用户设置的代理接口,如果没有检查和设置代理类是否是一个接口 if (specifiedInterfaces.length == 0) { // No user-specified interfaces: check whether target class is an interface. Class> targetClass = advised.getTargetClass(); if (targetClass != null) { if (targetClass.isInterface()) { advised.setInterfaces(targetClass); } else if (Proxy.isProxyClass(targetClass)) { advised.setInterfaces(targetClass.getInterfaces()); } specifiedInterfaces = advised.getProxiedInterfaces(); } } // 如果用户代理的接口设置中没有SpringProxy接口,需要把代理类实现SpringProxy接口,该接口是个标记接口,说明是Spring代理 boolean addSpringProxy = !advised.isInterfaceProxied(SpringProxy.class); // 如果代理类可以转化为Advised类型,并且用户没有指定Advised,则添加该接口, //所以这里可以知道一般Spring的代理类都实现了该Advised接口 boolean addAdvised = !advised.isOpaque() && !advised.isInterfaceProxied(Advised.class); //如果decoratingProxy==true,并且用户未添加DecoratingProxy接口,则代理需要实现该接口DecoratingProxy boolean addDecoratingProxy = (decoratingProxy && !advised.isInterfaceProxied(DecoratingProxy.class)); int nonUserIfcCount = 0; if (addSpringProxy) { nonUserIfcCount++; } if (addAdvised) { nonUserIfcCount++; } if (addDecoratingProxy) { nonUserIfcCount++; } Class>[] proxiedInterfaces = new Class>[specifiedInterfaces.length + nonUserIfcCount]; System.arraycopy(specifiedInterfaces, 0, proxiedInterfaces, 0, specifiedInterfaces.length); int index = specifiedInterfaces.length; if (addSpringProxy) { proxiedInterfaces[index] = SpringProxy.class; index++; } if (addAdvised) { proxiedInterfaces[index] = Advised.class; index++; } if (addDecoratingProxy) { proxiedInterfaces[index] = DecoratingProxy.class; } // 所以从上面分析得知,proxiedInterfaces会返回用户制定的代理接口+SpringProxy、Advised、DecoratingProxy return proxiedInterfaces; }
三、测试
public interface Human { Human getInstance(); }
public class ChineseHuman implements Human { private String desc; public ChineseHuman() { } public ChineseHuman(String desc) { this.desc = desc; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } @Override public Human getInstance() { System.out.println("human desc:" + desc); return this; } }
public class JdkDynamicAopProxyTests { @Test public void testJdkProxy() { AdvisedSupport advisedSupport = new AdvisedSupport(); advisedSupport.setInterfaces(Human.class); advisedSupport.setTargetSource(new TargetSource() { @Override public Class> getTargetClass() { return ChineseHuman.class; } @Override public boolean isStatic() { return false; } @Override public Object getTarget() throws Exception { return new ChineseHuman("中国人"); } @Override public void releaseTarget(Object target) throws Exception { } }); JdkDynamicAopProxy jdkDynamicAopProxy = new JdkDynamicAopProxy(advisedSupport); Human human = (Human) Proxy.newProxyInstance(JdkDynamicAopProxy.class.getClassLoader(), new Class[]{Human.class}, jdkDynamicAopProxy); System.out.println(human.getInstance()); // JDK原生代理,必然为true,因为本身是生成的是代理的接口的对象 System.out.println("human instanceof Human:" + (human instanceof Human)); //false System.out.println("human instanceof ChineseHuman:" + (human instanceof ChineseHuman)); //false System.out.println("human instanceof Advised:" + (human instanceof Advised)); //false System.out.println("human instanceof SpringProxy:" + (human instanceof SpringProxy)); //false System.out.println("human instanceof DecoratingProxy:" + (human instanceof DecoratingProxy)); //true, 有个面试题是这么问的,java动态代理为啥代理是接口,不能是类, // 其根原在于JDK的动态代理实现方式是代理对象继承了java.lang.reflect.Proxy,并且java单继承,所以无法代理类 System.out.println("human instanceof Proxy:" + (human instanceof Proxy)); System.out.println("Spring JDK代理扩展========="); human = (Human) jdkDynamicAopProxy.getProxy(); System.out.println(human.getInstance()); // 该代理对象的getInstance返回是其本身,原因也在于上面分析的红色部分原因。 System.out.println("human== human.getInstance():" + (human == human.getInstance())); // true System.out.println("human instanceof Human:" + (human instanceof Human)); //false System.out.println("human instanceof ChineseHuman:" + (human instanceof ChineseHuman)); //true System.out.println("human instanceof Advised:" + (human instanceof Advised)); // true System.out.println("human instanceof SpringProxy:" + (human instanceof SpringProxy)); // true System.out.println("human instanceof DecoratingProxy:" + (human instanceof DecoratingProxy)); //true System.out.println("human instanceof Proxy:" + (human instanceof Proxy)); } }
从上面的测试可以知道,一个对象被Spring的JDK动态代理后,其代理对象会实现其用户指定的代理接口外,还会实现Advised,SpringProxy,DecoratingProxy接口。