spring產生的代理物件都會實現SpringProxy介面原理探究【SpringProxy】
阿新 • • 發佈:2018-12-31
Spring使用JDK動態代理或者CGLIB的方式來生成代理物件,其中每個代理物件都會實現SpringProxy介面。具體原理請接著往下看:
JDK動態代理建立代理的方法如下所示:
public Object getProxy(@Nullable ClassLoader classLoader) { .... Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true); findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); }
下面是CGLIB建立代理的方法:
@Override public Object getProxy(@Nullable ClassLoader classLoader) { .... // Configure CGLIB Enhancer... Enhancer enhancer = createEnhancer(); if (classLoader != null) { enhancer.setClassLoader(classLoader); if (classLoader instanceof SmartClassLoader && ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) { enhancer.setUseCache(false); } } enhancer.setSuperclass(proxySuperClass); enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised)); enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE); enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader)); .... }
無論是哪一種方式,都呼叫了以下的方法
AopProxyUtils.completeProxiedInterfaces(this.advised)
該方法的作用是:根據Advised物件獲取代理物件需要實現的介面列表。
程式碼如下所示:
static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised, boolean decoratingProxy) { ... //advised.isInterfaceProxied(SpringProxy.class)表示代理物件本來實現的介面列表中是否包含SpringProxy介面 boolean addSpringProxy = !advised.isInterfaceProxied(SpringProxy.class); ... Class<?>[] proxiedInterfaces = new Class<?>[specifiedInterfaces.length + nonUserIfcCount]; ... //如果介面列表不包含SpringProxy介面,動態新增SpringProxy介面,所以代理物件始終會實現SpringProxy介面 if (addSpringProxy) { proxiedInterfaces[index] = SpringProxy.class; index++; } return proxiedInterfaces; }
在這個方法中給代理物件需要實現的介面列表proxiedInterfaces中動態添加了SpringProxy介面,所以經過spring建立的代理物件都將實現SpringProxy介面。