日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring源码-AOP(六)-自动代理与DefaultAdvisorAutoProxyCreator

發布時間:2025/4/5 javascript 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring源码-AOP(六)-自动代理与DefaultAdvisorAutoProxyCreator 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

2019獨角獸企業重金招聘Python工程師標準>>>

Spring AOP 源碼解析系列,建議大家按順序閱讀,歡迎討論

  • Spring源碼-AOP(一)-代理模式
  • Spring源碼-AOP(二)-AOP概念
  • Spring源碼-AOP(三)-Spring AOP的四種實現
  • Spring源碼-AOP(四)-ProxyFactory
  • Spring源碼-AOP(五)-ProxyFactoryBean
  • Spring源碼-AOP(六)-自動代理與DefaultAdvisorAutoProxyCreator
  • Spring源碼-AOP(七)-整合AspectJ
  • 框架存在的意義,簡單來說就是將復雜的底層實現封裝起來,并提供便捷的外部接口供用戶使用。對于Spring AOP而言,不論是ProxyFactory還是ProxyFactoryBean,都不能滿足實際業務中復雜的應用,用戶不可能對每個使用AOP代理的類進行配置。這時通過一定規則自動發現和代理自然應運而生。在spring-aop工程的autoproxy目錄構成了Spring AOP自動代理的基礎,AbstractAutoProxyCreator是自動代理實現的抽象基類,BeanNameAutoProxyCreator和DefaultAdvisorAutoProxyCreator則是Spring提供的兩個實現。

    自動代理的實現原理同ProxyFactoryBean中使用FactoryBean擴展不同,而是通過BeanPostProcessor擴展對Bean對象的創建過程進行控制來實現AOP代理。抽象基類AbstractAutoProxyCreator實現了BeanPostProcessor的子接口SmartInstantiationAwareBeanPostProcessor。先來了解下這個子接口。

    1.擴展接口SmartInstantiationAwareBeanPostProcessor

    我們常提及的BeanPostProcessor擴展并不是只有BeanPostProcessor一個接口,而是由其形成的多層接口體系,對Bean對象在IOC容器的創建過程的各個節點擴展形成的體系。這里只展示下SmartInstantiationAwareBeanPostProcessor的類結構。

    BeanPostProcessor

    • postProcessBeforeInitialization 初始化前擴展(執行init-method前)
    • postProcessAfterInitialization 初始化后擴展(執行init-method后)

    InstantiationAwareBeanPostProcessor

    • postProcessBeforeInstantiation 對象實例化前擴展
    • postProcessAfterInstantiation 對象實例化后擴展
    • postProcessPropertyValues 屬性依賴注入前擴展

    SmartInstantiationAwareBeanPostProcessor

    • predictBeanType 預測bean的類型,在beanFactory的getType時被調用
    • determineCandidateConstructors 對象實例化時決定要使用的構造函數時被調用
    • getEarlyBeanReference 循環依賴處理時獲取Early對象引用時被調用

    而對于Spring AOP的自動代理,處理的階段有兩個,對象實例化前擴展和初始化后擴展。

    2.自動代理基類AbstractAutoProxyCreator

    在對象實例化前(postProcessBeforeInstantiation)的擴展中,主要對配置了customTargetSourceCreators屬性的情況進行處理,而默認的處理都是在初始化后(postProcessAfterInitialization)擴展里執行的。

    對象實例化前postProcessBeforeInstantiation

    所謂的customTargetSourceCreators屬性是在AbstractAutoProxyCreator中的一個TargetSourceCreator數組,用來對代理對象target的封裝類TargetSource的生成進行自定義。spring內置的TargetSourceCreator有兩個:LazyInitTargetSourceCreator和QuickTargetSourceCreator。

    • LazyInitTargetSourceCreator:創建的代理對象并沒有初始化,直到第一次調用時才進行初始化

    • QuickTargetSourceCreator:根據beanName的不同前綴創建三種常用的TargetSource類型(bean必須為多例)

    • CommonsPoolTargetSource:池化TargetSource,每次執行方法時從池中取代理對象,執行完方法再返回池中
    • ThreadLocalTargetSource:線程級的TargetSource
    • PrototypeTargetSource:多例TargetSource,每次執行方法創建新的代理對象,執行完銷毀該對象

    來看下核心代碼

    if (beanName != null) {// 獲取自定義TargetSourceTargetSource targetSource = getCustomTargetSource(beanClass, beanName);if (targetSource != null) {this.targetSourcedBeans.add(beanName);// 獲取攔截器Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);// 創建代理對象Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);this.proxyTypes.put(cacheKey, proxy.getClass());return proxy;} }

    第一步獲取定義TargetSource,即遍歷所有自定義TargetSourceCreator,調用getTargetSource方法返回TargetSource。

    protected TargetSource getCustomTargetSource(Class<?> beanClass, String beanName) {// We can't create fancy target sources for directly registered singletons.if (this.customTargetSourceCreators != null &&this.beanFactory != null && this.beanFactory.containsBean(beanName)) {for (TargetSourceCreator tsc : this.customTargetSourceCreators) {TargetSource ts = tsc.getTargetSource(beanClass, beanName);if (ts != null) {// Found a matching TargetSource.if (logger.isDebugEnabled()) {logger.debug("TargetSourceCreator [" + tsc +" found custom TargetSource for bean with name '" + beanName + "'");}return ts;}}}// No custom TargetSource found.return null; }

    第二步獲取攔截器由子類實現,根據不同的方式獲取當前bean的攔截器,在后文以子類DefaultAdvisorAutoProxyCreator為例詳細介紹。

    第三步創建代理對象,通過創建ProxyFactory的方式完成,原理細節見ProxyFactory,來簡單看下它的實現。

    protected Object createProxy(Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {ProxyFactory proxyFactory = new ProxyFactory();// copy代理配置,如proxyTargetClass,exposeProxy等proxyFactory.copyFrom(this);// proxyTargetClass=false時if (!proxyFactory.isProxyTargetClass()) {// 再次確認是否要代理類對象if (shouldProxyTargetClass(beanClass, beanName)) {proxyFactory.setProxyTargetClass(true);}// 不需要則獲取其代理接口集合else {evaluateProxyInterfaces(beanClass, proxyFactory);}}// 將所有攔截器封裝成AdvisorAdvisor[] advisors = buildAdvisors(beanName, specificInterceptors);for (Advisor advisor : advisors) {proxyFactory.addAdvisor(advisor);}proxyFactory.setTargetSource(targetSource);// 擴展點,支持子類對ProxyFacory擴展customizeProxyFactory(proxyFactory);proxyFactory.setFrozen(this.freezeProxy);if (advisorsPreFiltered()) {proxyFactory.setPreFiltered(true);}// 創建代理對象return proxyFactory.getProxy(getProxyClassLoader()); }

    可以說邏輯非常清晰,最后使用ProxyFactory創建代理對象也是使用ProxyFactory統一的API。如果最終返回的代理對象不為空,則直接返回代理對象,不再執行IOC中的對象屬性注入和初始化等操作了。

    初始化后(postProcessAfterInitialization)

    如果并沒有設置自定義TargetSourceCreator,代理對象就會在原始對象初始化完成后創建。

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (bean != null) {Object cacheKey = getCacheKey(bean.getClass(), beanName);if (!this.earlyProxyReferences.contains(cacheKey)) {return wrapIfNecessary(bean, beanName, cacheKey);}}return bean; }

    wrapIfNecessary方法執行代理的核心操作。

    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {if (beanName != null && this.targetSourcedBeans.contains(beanName)) {return bean;}if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {return bean;}// AOP體系的子類不被代理(Advisor,Advice等)if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {this.advisedBeans.put(cacheKey, Boolean.FALSE);return bean;}// Create proxy if we have advice.// 獲取攔截器Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);if (specificInterceptors != DO_NOT_PROXY) {this.advisedBeans.put(cacheKey, Boolean.TRUE);// 創建代理對象Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));this.proxyTypes.put(cacheKey, proxy.getClass());return proxy;}this.advisedBeans.put(cacheKey, Boolean.FALSE);return bean; }

    實現過程基本同之前的一直,由子類返回攔截器集合,創建ProxyFactory對象進行代理。

    3.默認自動代理類DefaultAdvisorAutoProxyCreator

    在基類AbstractAutoProxyCreator中通過BeanPostProcessor擴展的方式,使得bean在創建過程中完成被代理。代理的框架已有AbstractAutoProxyCreator基本完成,留給子類的是獲取攔截器getAdvicesAndAdvisorsForBean方法的具體實現。我們以DefaultAdvisorAutoProxyCreator為例,了解下Spring AOP是如何完成自動發現和過濾切面的。

    DefaultAdvisorAutoProxyCreator的獲取攔截器實現其實由其抽象基類AbstractAdvisorAutoProxyCreator實現。

    protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);if (advisors.isEmpty()) {return DO_NOT_PROXY;}return advisors.toArray(); }

    實際操作有findEligibleAdvisors執行

    protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {// 尋找所有Advisor候選者List<Advisor> candidateAdvisors = findCandidateAdvisors();// 獲取匹配當前bean的AdvisorList<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);extendAdvisors(eligibleAdvisors);if (!eligibleAdvisors.isEmpty()) {// 對Advisor排序eligibleAdvisors = sortAdvisors(eligibleAdvisors);}return eligibleAdvisors; }

    主要過程分為兩步,第一步尋找所有Advisor候選者,即自動發現切面,第二部篩選當前bean的Advisor。

    findCandidateAdvisors由BeanFactoryAdvisorRetrievalHelper幫助類執行,原理就是從BeanFactory及其所有父級BeanFactory中尋找類型為Advisor的類,并執行getBean實例化。

    public List<Advisor> findAdvisorBeans() {// Determine list of advisor bean names, if not cached already.String[] advisorNames = null;synchronized (this) {advisorNames = this.cachedAdvisorBeanNames;if (advisorNames == null) {// Do not initialize FactoryBeans here: We need to leave all regular beans// uninitialized to let the auto-proxy creator apply to them!// 尋找Advisor類型的beanadvisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Advisor.class, true, false);this.cachedAdvisorBeanNames = advisorNames;}}if (advisorNames.length == 0) {return new LinkedList<Advisor>();}List<Advisor> advisors = new LinkedList<Advisor>();for (String name : advisorNames) {if (isEligibleBean(name)) {if (this.beanFactory.isCurrentlyInCreation(name)) {if (logger.isDebugEnabled()) {logger.debug("Skipping currently created advisor '" + name + "'");}}else {try {// getBean實例化advisors.add(this.beanFactory.getBean(name, Advisor.class));}catch (BeanCreationException ex) {Throwable rootCause = ex.getMostSpecificCause();if (rootCause instanceof BeanCurrentlyInCreationException) {BeanCreationException bce = (BeanCreationException) rootCause;if (this.beanFactory.isCurrentlyInCreation(bce.getBeanName())) {if (logger.isDebugEnabled()) {logger.debug("Skipping advisor '" + name +"' with dependency on currently created bean: " + ex.getMessage());}// Ignore: indicates a reference back to the bean we're trying to advise.// We want to find advisors other than the currently created bean itself.continue;}}throw ex;}}}}return advisors; }

    findAdvisorsThatCanApply篩選Advisor是由AopUtils類實現。對不同類型的Advisor進行不同的處理,如IntroductionAdvisor和PointcutAdvisor。

    public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {if (candidateAdvisors.isEmpty()) {return candidateAdvisors;}List<Advisor> eligibleAdvisors = new LinkedList<Advisor>();for (Advisor candidate : candidateAdvisors) {if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {eligibleAdvisors.add(candidate);}}boolean hasIntroductions = !eligibleAdvisors.isEmpty();for (Advisor candidate : candidateAdvisors) {if (candidate instanceof IntroductionAdvisor) {// already processedcontinue;}// 匹配Advisor是否適用當前beanif (canApply(candidate, clazz, hasIntroductions)) {eligibleAdvisors.add(candidate);}}return eligibleAdvisors; }

    其中canApply方法執行實際的匹配操作,細節部分主要是對切入點Pointcut和bean的匹配,有興趣的可以自己深入研究其匹配過程。

    public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {if (advisor instanceof IntroductionAdvisor) {return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);}else if (advisor instanceof PointcutAdvisor) {PointcutAdvisor pca = (PointcutAdvisor) advisor;return canApply(pca.getPointcut(), targetClass, hasIntroductions);}else {// It doesn't have a pointcut so we assume it applies.return true;} }

    至此也就完成了bean適用的Advisor切面的自動發現與篩選,最后由ProxyFactory完成代理創建。

    4.AOP中的循環依賴

    在看自動代理源碼的過程中,突然注意到SmartInstantiationAwareBeanPostProcessor接口中的getEarlyBeanReference方法,它是Spring處理循環依賴時返回**未創建完(只實例化未做依賴注入)**Bean的擴展。關于循環依賴可以去Bean的循環依賴一章去詳細了解,這里只做簡單的說明。

    有兩個單例Bean,A和B,A中引用了B,B中引用了A。Spring對這種相互依賴做了特殊的處理,即在對象實例化后緩存一份key為beanName的ObjectFactory,ObjectFactory中的getObject方法返回當前創建對象的引用。

    // 支持單例依賴循環 if (earlySingletonExposure) {// 添加Early對象緩存addSingletonFactory(beanName, new ObjectFactory<Object>() {[@Override](https://my.oschina.net/u/1162528)public Object getObject() throws BeansException {return getEarlyBeanReference(beanName, mbd, bean);}}); }

    這里假設先創建A對象實例,當A進行依賴注入時,需要B對象,則會通過getBean方法創建B對象。此時A并沒有創建完成,但在Early緩存中存有A的引用,因而當B對象進行依賴注入A時,直接返回A對象的Early引用,從而不會造成陷入無休止的依賴注入循環中。

    在getEarlyBeanReference方法中,不僅只是返回對象引用,還有一個擴展點,支持SmartInstantiationAwareBeanPostProcessor接口中的getEarlyBeanReference方法對返回的對象引用進行修改。

    protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {Object exposedObject = bean;if (bean != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;// 擴展點,對Early對象進行修改exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);if (exposedObject == null) {return exposedObject;}}}}return exposedObject; }

    回到AOP的自動代理上,在AbstractAutoProxyCreator中實現了getEarlyBeanReference擴展

    public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {Object cacheKey = getCacheKey(bean.getClass(), beanName);if (!this.earlyProxyReferences.contains(cacheKey)) {this.earlyProxyReferences.add(cacheKey);}return wrapIfNecessary(bean, beanName, cacheKey); }

    這里將標識唯一bean的cacheKey添加到earlyProxyReferences中,在之后bean的初始化中將很有用。然后執行wrapIfNecessary返回bean的代理對象,因而如果存在循環依賴,則依賴注入的就是真正的代理對象。

    在對象執行完依賴注入后,進行初始化操作,會調用初始化后擴展postProcessAfterInitialization方法,再來關注下AbstractAutoProxyCreator此方法的實現。

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (bean != null) {Object cacheKey = getCacheKey(bean.getClass(), beanName);// 判斷early引用中是否包含cacheKeyif (!this.earlyProxyReferences.contains(cacheKey)) {return wrapIfNecessary(bean, beanName, cacheKey);}}return bean; }

    它判斷了earlyProxyReferences中不包含當前bean的cacheKey才會執行代理操作,也就是說,如果存在循環依賴時,代理對象在getEarlyBeanReference時就創建了,而在初始化后直接跳過了,返回的bean是原始的對象。

    你可能會問,既然這里返回的不是代理對象,那代理對象最后是怎樣返回的呢?

    Spring在對象進行初始化后,對存在循環依賴的又做了巧妙的處理。

    if (earlySingletonExposure) {// 如果存在循環依賴,則返回的為代理對象Object earlySingletonReference = getSingleton(beanName, false);if (earlySingletonReference != null) {// 循環依賴下,經過初始化后的對象同原始對象一致// 因而將代理對象賦給最終返回的對象引用if (exposedObject == bean) {exposedObject = earlySingletonReference;}} }

    這里的設計很是巧妙,需要結合依賴循環的處理,AOP對象的處理統一來理解。同時對循環依賴時,不直接緩存對象,而是通過ObjectFactory的方式有了更深的理解。有興趣的同學可以反復琢磨一下。

    2017/12/24更新

    回頭再看這個循環依賴的點,還是花了一點時間來回翻了下源碼才理解,因此再補充記錄下。getSingleton(beanName, false)方法,當不存在循環依賴時,會返回null,而存在循環依賴時,返回的是ObjectFactory的getEarlyBeanReference方法返回的對象。原始的bean對象經過getEarlyBeanReference方法后,可能存在SmartInstantiationAwareBeanPostProcessor處理器,在其getEarlyBeanReference方法中被改變了,比如AbstractAutoProxyCreator中會返回代理對象。而在AbstractAutoProxyCreator的實現中,使用cacheKey保證了生成的代理對象是單例的。因此當if (exposedObject == bean)判斷時會返回true,從而getBean方法返回的對象就是真正的代理對象。此時還有一個疑問,代理對象并沒有進行屬性的依賴注入以及init-method等的初始化啊?其實代理對象沒有必要去復制原始對象的內部結構,因為它持有原始對象的引用,并且實際調用方法是交由原始對象去處理的。

    總結

    Spring AOP的自動代理,它同ProxyFactoryBean采用了不同的擴展方式。FactoryBean的擴展思路非常清晰,在工廠ProxyFactoryBean創建完成后直接根據其配置動態生成不同的代理對象,適用于簡單的配置,但在ApplicationContext高級容器中,就需要通過BeanPostProcessor擴展進行更細粒度的操作,從而支持復雜的業務配置。而接下來要討論的AspectJ整合Spring的基礎實現,就來自于Spring AOP的自動代理。

    轉載于:https://my.oschina.net/u/2377110/blog/1517915

    總結

    以上是生活随笔為你收集整理的Spring源码-AOP(六)-自动代理与DefaultAdvisorAutoProxyCreator的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 狠狠躁夜夜躁xxxxaaaa | 天堂成人国产精品一区 | 日本成人激情 | 亚洲av永久无码精品一百度影院 | 爱乃なみ加勒比在线播放 | 久久无码人妻一区二区三区 | www欧美| 黄瓜视频在线免费看 | 老妇free性videosxx | 国产精品1页 | 91在线观看网站 | 日本五十肥熟交尾 | 91精品国产综合久久久蜜臀 | 久久特黄 | 中文字幕在线看人 | 亚洲av综合av一区二区三区 | 天天草比 | 国产无遮挡又黄又爽又色 | 国产99自拍 | 精品日韩欧美 | 久久久久久久黄色 | 自拍偷拍国内 | 天天干天天操天天舔 | 一区不卡在线观看 | 999在线观看视频 | 天堂av免费在线观看 | 日韩欧美毛片 | 激情av在线| 亚洲制服一区二区 | 9i看片成人免费看片 | 免费在线观看视频a | 午夜性福利视频 | 777视频在线观看 | 9999热视频 | 久久国产香蕉视频 | 就去吻亚洲 | xx99小雪| 无码国产精品高潮久久99 | 明日叶三叶 | www.国产精品| 亚洲成人二区 | 成人激情视频在线观看 | 日韩黄色三级视频 | 色偷偷人人澡人人爽人人模 | 亚洲日本片 | www.国产毛片 | 国产草草 | 在线观看黄色免费网站 | 激情视频在线免费观看 | 性久久 | 超碰美女 | 色哟哟在线播放 | 国产一区二区在线免费观看视频 | 老司机av影院 | a天堂中文字幕 | 一级作爱片| 国产理论av | 国产婷婷色一区二区三区 | 国产18精品乱码免费看 | 国产乱码久久久 | 一区自拍| 青草一区二区 | 91午夜交换视频 | 欧美精品v国产精品v日韩精品 | 成人免费在线网站 | 一区二区播放 | 久久精品女人毛片国产 | 亚洲av久久久噜噜噜噜 | 肥熟女一区二区三肥熟女 | 国产调教视频在线观看 | 在线免费中文字幕 | 中文字幕一区二区在线视频 | 亚洲精选久久久 | 鸥美毛片 | 午夜视频在线观看国产 | 国产伦精品一区二区三区免.费 | 99精品人妻少妇一区二区 | 在线99 | 日本伊人色 | 四虎成人在线视频 | 中文字幕第一页在线视频 | 欧美性猛交xxxx乱大交俱乐部 | 日本一级吃奶淫片免费 | 国产suv精品一区二区60 | 日韩最新视频 | 超碰在线观看av | 中文字幕1页 | 精东传媒在线 | 国产精品色图 | 少妇厨房愉情理伦bd在线观看 | 国产成人无码一区二区在线播放 | 亚洲AV无码精品久久一区二区 | 67194成人 | 美女福利视频网 | 我色综合 | 欧美性生活精品 | 少妇第一次交换又紧又爽 | 久久精品在线免费观看 | 亚洲一区和二区 |