本篇內(nèi)容介紹了“spring中代理的創(chuàng)建方法有哪些”的有關(guān)知識,在實(shí)際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
創(chuàng)新互聯(lián)公司是一家集網(wǎng)站建設(shè),準(zhǔn)格爾企業(yè)網(wǎng)站建設(shè),準(zhǔn)格爾品牌網(wǎng)站建設(shè),網(wǎng)站定制,準(zhǔn)格爾網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營銷,網(wǎng)絡(luò)優(yōu)化,準(zhǔn)格爾網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競爭力。可充分滿足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶成長自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。
spring 中創(chuàng)建代理使用了 Jdk 和 Cglib 兩種方式創(chuàng)建,JdkDynamicAopProxy
和 ObjenesisCglibAopProxy
,通過使用配置 Advised
和 ProxyConfig
來管理配置,根據(jù)配置決定使用哪種方式創(chuàng)建代理,下面來介紹這幾個關(guān)鍵的類。
Advised 是一個管理 AOP 代理工廠配置的接口,在spring中的所有AopProxy都可以轉(zhuǎn)換為 Advised。
在 spring 中,使用 ProxyConfig
來配置代理創(chuàng)建屬性。
/** * 代理工廠的超類,用于統(tǒng)一管理代理工廠類的屬性。 */ public class ProxyConfig implements Serializable { // true:使用子類代理,false:使用接口代理 private boolean proxyTargetClass = false; // 啟動代理優(yōu)化 private boolean optimize = false; // 使用該代理工長創(chuàng)建的代理是否可以轉(zhuǎn)換為 Advised,默認(rèn)為false:表示可以, // 如果為false,可以將bean轉(zhuǎn)換為Advised:Advised testBean = (Advised) context.getBean("testBean"); boolean opaque = false; // 將代理暴露出去,綁定到 ThreadLocal 的 currentProxy,用于代理類自己的方法調(diào)用自己的場景。 boolean exposeProxy = false; // 凍結(jié)配置,true:不能修改該代理工長的配置。 private boolean frozen = false; }
實(shí)現(xiàn)了ProxyConfig
的直接子類有4個:
ScopedProxyFactoryBean、ProxyProcessorSupport、AbstractSingletonProxyFactoryBean、AdvisedSupport
,這幾個類使用不同的方式來創(chuàng)建代理,但是最后還是會將創(chuàng)建代理的工作委托給 ProxyFactory
,下面來查看4個直接子類的相關(guān)代碼。
ScopedProxyFactoryBean
:用于@Scope 注解,實(shí)現(xiàn)bean的作用域控制。他實(shí)現(xiàn)了 BeanFactory
、BeanFactoryAware
接口,具有創(chuàng)建、管理bean的能力。
這個類生成的代理只會記錄類的名稱,然后根據(jù)作用域獲取bean,如果是prototype的,則beanFactory會創(chuàng)建一個新的bean。
public class ScopedProxyFactoryBean extends ProxyConfig implements FactoryBean
ProxyProcessorSupport
:為 ProxyFactory
提供了常用的公共方法。
public class ProxyProcessorSupport extends ProxyConfig implements Ordered, BeanClassLoaderAware, AopInfrastructureBean { /** * 可以自定義排序 */ public void setOrder(int order) { this.order = order; } @Override public int getOrder() { return this.order; } /** * 當(dāng)實(shí)現(xiàn)了接口時(shí),使用接口代理,沒有實(shí)現(xiàn)接口則使用類代理。 */ protected void evaluateProxyInterfaces(Class> beanClass, ProxyFactory proxyFactory) { Class>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader()); boolean hasReasonableProxyInterface = false; for (Class> ifc : targetInterfaces) { if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) && ifc.getMethods().length > 0) { hasReasonableProxyInterface = true; break; } } if (hasReasonableProxyInterface) { for (Class> ifc : targetInterfaces) { proxyFactory.addInterface(ifc); } } else { proxyFactory.setProxyTargetClass(true); } } }
AbstractSingletonProxyFactoryBean
: 創(chuàng)建單例代理對象,在需要代理的對象實(shí)例化后,使用 InitializingBean#afterPropertiesSet()
來創(chuàng)建代理,并為其設(shè)置前置通知和后置通知。
public abstract class AbstractSingletonProxyFactoryBean extends ProxyConfig implements FactoryBean
AdvisedSupport
:實(shí)現(xiàn)了 Advised
,將 ProxyConfig
與 Advised
進(jìn)行適配,為 Advised
提供了支持,他的唯一子類 ProxyCreatorSupport
為創(chuàng)建代理提供了支持。
public class AdvisedSupport extends ProxyConfig implements Advised { // 空代理對象 public static final TargetSource EMPTY_TARGET_SOURCE = EmptyTargetSource.INSTANCE; // 代理目標(biāo)源:默認(rèn)為空目標(biāo)源 TargetSource targetSource = EMPTY_TARGET_SOURCE; // 是否已經(jīng)對Advisors進(jìn)行了過慮 private boolean preFiltered = false; // Advisor 調(diào)用鏈工長 AdvisorChainFactory advisorChainFactory = new DefaultAdvisorChainFactory(); // 緩存方法對應(yīng)的 Advisor 調(diào)用鏈。 private transient Map> methodCache; // 要實(shí)現(xiàn)的代理接口,按順序存儲。 private List > interfaces = new ArrayList<>(); // Advisor 列表 private List advisors = new ArrayList<>(); // Advisor 數(shù)據(jù),為了方便內(nèi)部操作。 private Advisor[] advisorArray = new Advisor[0]; }
ProxyCreatorSupport
為創(chuàng)建代理提供了支持,他使用了AopProxyFactory
來創(chuàng)建AopProxy
,最后ProxyFactory
使用 AopProxy
來創(chuàng)建代理對象。
在創(chuàng)建ProxyCreatorSupport
時(shí)默認(rèn)創(chuàng)建 DefaultAopProxyFactory
,由他來判斷使用接口代理還是子類代理。
public class ProxyCreatorSupport extends AdvisedSupport { private AopProxyFactory aopProxyFactory; private final Listlisteners = new LinkedList<>(); // 在創(chuàng)建第一個代理后將置為true,表示進(jìn)入活動狀態(tài),將會觸發(fā) listeners。 private boolean active = false; /** * 無參構(gòu)造器,將會創(chuàng)建一個默認(rèn)的aopProxyFactory。 * DefaultAopProxyFactory 是一個創(chuàng)建代理的工長,用于根據(jù)配置創(chuàng)建代理。 */ public ProxyCreatorSupport() { this.aopProxyFactory = new DefaultAopProxyFactory(); } // 創(chuàng)建AOP代理,根據(jù)自身的配置屬性覺得使用JDK代理還是Cglib代理。 protected final synchronized AopProxy createAopProxy() { if (!this.active) { activate(); } return getAopProxyFactory().createAopProxy(this); } }
上面提到使用 DefaultAopProxyFactory
來決定使用 jdk代理還是 Cglib代理,他通過接收一個 AdvisedSupport
// AopProxy 工廠 public class DefaultAopProxyFactory implements AopProxyFactory, Serializable { @Override public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { // 啟用優(yōu)化或使用子類代理、沒有實(shí)現(xiàn)接口,就會使用子類代理方式。 if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class> targetClass = config.getTargetClass(); if (targetClass == null) { throw new AopConfigException("TargetSource cannot determine target class: " + "Either an interface or a target is required for proxy creation."); } // 代理目標(biāo)是接口,或者也是一個代理對象,使用jdk代理,否則使用Cglib 代理 if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); } return new ObjenesisCglibAopProxy(config); } // 使用接口代理:JDK代理 else { return new JdkDynamicAopProxy(config); } } }
ProxyFactory
是ProxyCreatorSupport
的子類,通過調(diào)用父類的方法獲取AopProxy
來創(chuàng)建目標(biāo)代理對象。
public class ProxyFactory extends ProxyCreatorSupport { public Object getProxy() { // 掉用 `ProxyCreatorSupport#createAopProxy` 方法之后根據(jù)配置來判斷使用 JDK生成代理還是 Cglib生成代理 return createAopProxy().getProxy(); } // 與上面的方法區(qū)別在于傳入了類加載器 public Object getProxy(@Nullable ClassLoader classLoader) { return createAopProxy().getProxy(classLoader); } }
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable { /** 代理配置. */ private final AdvisedSupport advised; /** * 代理的接口上是否定義了equals方法 */ private boolean equalsDefined; /** * 代理的接口是否定義了hashCode 方法 */ private boolean hashCodeDefined; public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException { Assert.notNull(config, "AdvisedSupport must not be null"); // 通知不為空,并且目標(biāo)源不為空。 if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) { throw new AopConfigException("No advisors and no TargetSource specified"); } this.advised = config; } // 創(chuàng)建代理 @Override public Object getProxy() { // 傳入默認(rèn)類加載器 return getProxy(ClassUtils.getDefaultClassLoader()); } @Override public Object getProxy(@Nullable ClassLoader classLoader) { if (logger.isTraceEnabled()) { logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource()); } // 獲取代理目標(biāo)類的所有接口 Class>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true); // 檢查接口是否實(shí)現(xiàn)了equals 和 hashCode 方法 findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); // 創(chuàng)建代理對象,這里傳入了this對象,因?yàn)?nbsp;JdkDynamicAopProxy 實(shí)現(xiàn)了 InvocationHandler,使用這一段代理邏輯進(jìn)行代理 return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); } /** * aop代理使用jdk代理將執(zhí)行的邏輯 */ @Override @Nullable public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object oldProxy = null; boolean setProxyContext = false; TargetSource targetSource = this.advised.targetSource; Object target = null; try { // 執(zhí)行equals方法時(shí),接口未定義 equals 方法 ,執(zhí)行JdkDynamicAopProxy 的 equals 方法 if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { return equals(args[0]); } // 執(zhí)行 hashCode 方法時(shí),接口未定義 hashCode 方法,執(zhí)行JdkDynamicAopProxy的hashCode方法 else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { return hashCode(); } // else if (method.getDeclaringClass() == DecoratingProxy.class) { return AopProxyUtils.ultimateTargetClass(this.advised); } // 能夠轉(zhuǎn)換為Advised,將轉(zhuǎn)換為Advised,然后執(zhí)行 else if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) { return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); } Object retVal; // 是否暴露當(dāng)前的代理,綁定到ThreadLocal中, if (this.advised.exposeProxy) { oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } // 獲取目標(biāo)對象 target = targetSource.getTarget(); Class> targetClass = (target != null ? target.getClass() : null); // 根據(jù)代理目標(biāo)對象和方法獲取切入點(diǎn)、方法攔截器等。 List
在 JdkDynamicAopProxy
中,有2處關(guān)鍵代碼,1是獲取代理目標(biāo)的接口,2是執(zhí)行切入點(diǎn)、攔截器。
AopProxyUtils#completeProxiedInterfaces()
方法獲取代理目標(biāo)的接口,按照規(guī)則添加一部分接口SpringProxy、Advised、DecoratingProxy
。
// AopProxyUtils static Class>[] completeProxiedInterfaces(AdvisedSupport advised, boolean decoratingProxy) { // 獲取目標(biāo)類實(shí)現(xiàn)的接口接口 Class>[] specifiedInterfaces = advised.getProxiedInterfaces(); // 目標(biāo)類的接口為空 if (specifiedInterfaces.length == 0) { // 獲取代理目標(biāo)class Class> targetClass = advised.getTargetClass(); if (targetClass != null) { // 判斷目標(biāo)類型是否是接口 if (targetClass.isInterface()) { advised.setInterfaces(targetClass); } // 代理目標(biāo)類型是代理 else if (Proxy.isProxyClass(targetClass)) { advised.setInterfaces(targetClass.getInterfaces()); } // 重新獲取代理對象的接口集 specifiedInterfaces = advised.getProxiedInterfaces(); } } // 如果目標(biāo)類未實(shí)現(xiàn) SpringProxy 接口,將添加 SpringProxy 到接口集中。 boolean addSpringProxy = !advised.isInterfaceProxied(SpringProxy.class); // 目標(biāo)類能轉(zhuǎn)換為Advised,并且未實(shí)現(xiàn) Advised 接口,則添加 Advised 到接口集中 boolean addAdvised = !advised.isOpaque() && !advised.isInterfaceProxied(Advised.class); // decoratingProxy 為true,且目標(biāo)類未實(shí)現(xiàn) DecoratingProxy 接口,將 DecoratingProxy 添加進(jìn)接口集中 boolean addDecoratingProxy = (decoratingProxy && !advised.isInterfaceProxied(DecoratingProxy.class)); // 劃分接口數(shù)組長度 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); // 將接口class設(shè)置進(jìn)對應(yīng)的數(shù)組位置 int index = specifiedInterfaces.length; if (addSpringProxy) { proxiedInterfaces[index] = SpringProxy.class; index++; } if (addAdvised) { proxiedInterfaces[index] = Advised.class; index++; } if (addDecoratingProxy) { proxiedInterfaces[index] = DecoratingProxy.class; } // 返回需要代理的接口集。 return proxiedInterfaces; }
執(zhí)行切面和方法攔截器邏輯 ReflectiveMethodInvocation#proceed
public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable { public Object proceed() throws Throwable { // 執(zhí)行完后通知或攔截器后,將執(zhí)行業(yè)務(wù)方法 if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return invokeJoinpoint(); } // 獲取通知或攔截器 Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); // 通知或攔截器是 InterceptorAndDynamicMethodMatcher // InterceptorAndDynamicMethodMatcher 用于將方法匹配器與攔截器結(jié)合,如果方法匹配器匹配了就是用攔截器進(jìn)行調(diào)用 if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice; Class> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass()); if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) { return dm.interceptor.invoke(this); } else { // 匹配失敗,調(diào)用下一個匹配的攔截器 return proceed(); } } // 調(diào)用其他攔截器,其他攔截器需要調(diào)用,因?yàn)閭魅肓藅his,攔截器鏈可以使用引用調(diào)用本方法,以執(zhí)行下一個切面或攔截器。 else { return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } } }
“spring中代理的創(chuàng)建方法有哪些”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!