电竞比分网-中国电竞赛事及体育赛事平台

分享

Spring事務(wù)處理時(shí)自我調(diào)用的解決方案及一些實(shí)現(xiàn)方式的風(fēng)險(xiǎn)

 feimishiwo 2015-06-15

     
        <
        >
     

      獵頭職位: 上海: Senior Software Engineer
     
   


       
     
                                           
相關(guān)文章:  
             
             
推薦群組: Hibernate
             
更多相關(guān)推薦
           

           
                         
     
     

前些日子一朋友在需要在目標(biāo)對(duì)象中進(jìn)行自我調(diào)用,且需要實(shí)施相應(yīng)的事務(wù)定義,且網(wǎng)上的一種通過(guò)BeanPostProcessor的解決方案是存在問(wèn)題的。因此專(zhuān)門(mén)寫(xiě)此篇帖子分析why。



1、預(yù)備知識(shí)


aop概念請(qǐng)參考【http://www./topic/1122401】和【http://jinnianshilongnian./blog/1418596


spring的事務(wù)管理,請(qǐng)參考【http://jinnianshilongnian./blog/1441271


 


 


使用AOP 代理后的方法調(diào)用執(zhí)行流程,如圖所示





也就是說(shuō)我們首先調(diào)用的是AOP代理對(duì)象而不是目標(biāo)對(duì)象,首先執(zhí)行事務(wù)切面,事務(wù)切面內(nèi)部通過(guò)TransactionInterceptor環(huán)繞增強(qiáng)進(jìn)行事務(wù)的增強(qiáng),即進(jìn)入目標(biāo)方法之前開(kāi)啟事務(wù),退出目標(biāo)方法時(shí)提交/回滾事務(wù)。



2、測(cè)試代碼準(zhǔn)備


Java代碼 復(fù)制代碼 收藏代碼
  1. public interface AService {  
  2.     public void a();  
  3.     public void b();  
  4. }  
  5.    
  6. @Service()  
  7. public class AServiceImpl1 implements AService{  
  8.     @Transactional(propagation = Propagation.REQUIRED)  
  9.     public void a() {  
  10.         this.b();  
  11.     }  
  12.     @Transactional(propagation = Propagation.REQUIRES_NEW)  
  13.     public void b() {  
  14.     }  
  15. }  

 



3、問(wèn)題


目標(biāo)對(duì)象內(nèi)部的自我調(diào)用將無(wú)法實(shí)施切面中的增強(qiáng),如圖所示



 


此處的this指向目標(biāo)對(duì)象,因此調(diào)用this.b()將不會(huì)執(zhí)行b事務(wù)切面,即不會(huì)執(zhí)行事務(wù)增強(qiáng),因此b方法的事務(wù)定義“@Transactional(propagation = Propagation.REQUIRES_NEW)”將不會(huì)實(shí)施,即結(jié)果是ba方法的事務(wù)定義是一樣的,可以從以下日志看出:


 


 org.springframework.transaction.annotation.AnnotationTransactionAttributeSource Adding transactional method 'a' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''


org.springframework.beans.factory.support.DefaultListableBeanFactory Returning cached instance of singleton bean 'txManager'


org.springframework.orm.hibernate4.HibernateTransactionManager Creating new transaction with name [com.sishuok.service.impl.AServiceImpl1.a]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''  -----創(chuàng)建a方法事務(wù)


org.springframework.orm.hibernate4.HibernateTransactionManager Opened new Session …… for Hibernate transaction  ---打開(kāi)Session


……


org.springframework.transaction.support.TransactionSynchronizationManager Initializing transaction synchronization


org.springframework.transaction.interceptor.TransactionInterceptor Getting transaction for [com.sishuok.service.impl.AServiceImpl1.a]


org.springframework.transaction.interceptor.TransactionInterceptor Completing transaction for [com.sishuok.service.impl.AServiceImpl1.a] ----完成a方法事務(wù)


org.springframework.orm.hibernate4.HibernateTransactionManager Triggering beforeCommit synchronization


org.springframework.orm.hibernate4.HibernateTransactionManager Triggering beforeCompletion synchronization


org.springframework.orm.hibernate4.HibernateTransactionManager Initiating transaction commit


 


org.springframework.orm.hibernate4.HibernateTransactionManager Committing Hibernate transaction on Session ……---提交a方法事務(wù)



org.springframework.orm.hibernate4.HibernateTransactionManager Rolling back Hibernate transaction on Session ……---如果有異常將回滾a方法事務(wù)


 


org.springframework.orm.hibernate4.HibernateTransactionManager Triggering afterCommit synchronization


org.springframework.orm.hibernate4.HibernateTransactionManager Triggering afterCompletion synchronization


org.springframework.transaction.support.TransactionSynchronizationManager Clearing transaction synchronization


……


org.springframework.orm.hibernate4.HibernateTransactionManager Closing Hibernate Session …… after transaction     --關(guān)閉Session


 


我們可以看到事務(wù)切面只對(duì)a方法進(jìn)行了事務(wù)增強(qiáng),沒(méi)有對(duì)b方法進(jìn)行增強(qiáng)。


 



3、解決方案


此處a方法中調(diào)用b方法時(shí),只要通過(guò)AOP代理調(diào)用b方法即可走事務(wù)切面,即可以進(jìn)行事務(wù)增強(qiáng),如下所示:


Java代碼 復(fù)制代碼 收藏代碼
  1. public void a() {  
  2. aopProxy.b();//即調(diào)用AOP代理對(duì)象的b方法即可執(zhí)行事務(wù)切面進(jìn)行事務(wù)增強(qiáng)  
  3. }  

 

判斷一個(gè)Bean是否是AOP代理對(duì)象可以使用如下三種方法:


AopUtils.isAopProxy(bean)         是否是代理對(duì)象;


AopUtils.isCglibProxy(bean)        是否是CGLIB方式的代理對(duì)象;


AopUtils.isJdkDynamicProxy(bean)  是否是JDK動(dòng)態(tài)代理方式的代理對(duì)象;



3.1、通過(guò)ThreadLocal暴露Aop代理對(duì)象


1、開(kāi)啟暴露Aop代理到ThreadLocal支持(如下配置方式從spring3開(kāi)始支持)


Java代碼 復(fù)制代碼 收藏代碼
  1. <aop:aspectj-autoproxy expose-proxy="true"/><!—注解風(fēng)格支持-->  

Java代碼 復(fù)制代碼 收藏代碼
  1. <aop:config expose-proxy="true"><!—xml風(fēng)格支持-->   

   


2、修改我們的業(yè)務(wù)實(shí)現(xiàn)類(lèi)


this.b();-----------修改為--------->((AService) AopContext.currentProxy()).b();


 


3、執(zhí)行測(cè)試用例,日志如下


 


 


org.springframework.beans.factory.support.DefaultListableBeanFactory Returning cached instance of singleton bean 'txManager'


org.springframework.orm.hibernate4.HibernateTransactionManager Creating new transaction with name [com.sishuok.service.impl.AServiceImpl2.a]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''   -----創(chuàng)建a方法事務(wù)


org.springframework.orm.hibernate4.HibernateTransactionManager Opened new Session ……for Hibernate transaction  --打開(kāi)a Session


org.springframework.orm.hibernate4.HibernateTransactionManager Preparing JDBC Connection of Hibernate Session ……


org.springframework.orm.hibernate4.HibernateTransactionManager Exposing Hibernate transaction as JDBC transaction ……


……


org.springframework.transaction.support.TransactionSynchronizationManager Initializing transaction synchronization


org.springframework.transaction.interceptor.TransactionInterceptor Getting transaction for [com.sishuok.service.impl.AServiceImpl2.a]


 


org.springframework.transaction.annotation.AnnotationTransactionAttributeSource Adding transactional method 'b' with attribute: PROPAGATION_REQUIRES_NEW,ISOLATION_DEFAULT; ''


……


org.springframework.orm.hibernate4.HibernateTransactionManager Suspending current transaction, creating new transaction with name [com.sishuok.service.impl.AServiceImpl2.b]  -----創(chuàng)建b方法事務(wù)(并暫停a方法事務(wù))


……


org.springframework.orm.hibernate4.HibernateTransactionManager Opened new Session  for Hibernate transaction  ---打開(kāi)b Session


……


org.springframework.transaction.support.TransactionSynchronizationManager Initializing transaction synchronization


org.springframework.transaction.interceptor.TransactionInterceptor Getting transaction for [com.sishuok.service.impl.AServiceImpl2.b]


org.springframework.transaction.interceptor.TransactionInterceptor Completing transaction for [com.sishuok.service.impl.AServiceImpl2.b] ----完成b方法事務(wù)


 


org.springframework.orm.hibernate4.HibernateTransactionManager Triggering beforeCommit synchronization


org.springframework.orm.hibernate4.HibernateTransactionManager Triggering beforeCompletion synchronization


org.springframework.orm.hibernate4.HibernateTransactionManager Initiating transaction commit


org.springframework.orm.hibernate4.HibernateTransactionManager Committing Hibernate transaction on Session …… ---提交b方法事務(wù)


org.springframework.orm.hibernate4.HibernateTransactionManager Triggering afterCommit synchronization


org.springframework.orm.hibernate4.HibernateTransactionManager Triggering afterCompletion synchronization


org.springframework.transaction.support.TransactionSynchronizationManager Clearing transaction synchronization


……


org.springframework.orm.hibernate4.HibernateTransactionManager Closing Hibernate Session …… after transaction  --關(guān)閉 b Session


 


-----到此b方法事務(wù)完畢


 


org.springframework.orm.hibernate4.HibernateTransactionManager Resuming suspended transaction after completion of inner transaction ---恢復(fù)a方法事務(wù)


……


org.springframework.transaction.support.TransactionSynchronizationManager Initializing transaction synchronization


org.springframework.transaction.interceptor.TransactionInterceptor Completing transaction for [com.sishuok.service.impl.AServiceImpl2.a] ----完成a方法事務(wù)


org.springframework.orm.hibernate4.HibernateTransactionManager Triggering beforeCommit synchronization


org.springframework.orm.hibernate4.HibernateTransactionManager Triggering beforeCompletion synchronization


org.springframework.orm.hibernate4.HibernateTransactionManager Initiating transaction commit


org.springframework.orm.hibernate4.HibernateTransactionManager Committing Hibernate transaction on Session ……---提交a方法事務(wù)


org.springframework.orm.hibernate4.HibernateTransactionManager Triggering afterCommit synchronization


org.springframework.orm.hibernate4.HibernateTransactionManager Triggering afterCompletion synchronization


org.springframework.transaction.support.TransactionSynchronizationManager Clearing transaction synchronization


……


org.springframework.orm.hibernate4.HibernateTransactionManager Closing Hibernate Session …… after transaction  --關(guān)閉 a Session


 


 


 


此處我們可以看到b方法的事務(wù)起作用了。


 


以上方式是解決目標(biāo)對(duì)象內(nèi)部方法自我調(diào)用并實(shí)施事務(wù)的最簡(jiǎn)單的解決方案。


 


4、實(shí)現(xiàn)原理分析



4.1、在進(jìn)入代理對(duì)象之后通過(guò)AopContext.serCurrentProxy(proxy)暴露當(dāng)前代理對(duì)象到ThreadLocal,并保存上次ThreadLocal綁定的代理對(duì)象為oldProxy;


4.2、接下來(lái)我們可以通過(guò) AopContext.currentProxy() 獲取當(dāng)前代理對(duì)象;


4.3、在退出代理對(duì)象之前要重新將ThreadLocal綁定的代理對(duì)象設(shè)置為上一次的代理對(duì)象,即AopContext.serCurrentProxy(oldProxy)


 


有些人不喜歡這種方式,說(shuō)通過(guò)ThreadLocal暴露有性能問(wèn)題,其實(shí)這個(gè)不需要考慮,因?yàn)槭聞?wù)相關(guān)的(SessionConnection)內(nèi)部也是通過(guò)SessionHolderConnectionHolder暴露到ThreadLocal實(shí)現(xiàn)的。


 


不過(guò)自我調(diào)用這種場(chǎng)景確實(shí)只有很少情況遇到,因此不用這種方式我們也可以通過(guò)如下方式實(shí)現(xiàn)。



3.2、通過(guò)初始化方法在目標(biāo)對(duì)象中注入代理對(duì)象


Java代碼 復(fù)制代碼 收藏代碼
  1. @Service  
  2. public class AServiceImpl3 implements AService{  
  3.     @Autowired  //①  注入上下文  
  4.     private ApplicationContext context;  
  5.       
  6.     private AService proxySelf; //②  表示代理對(duì)象,不是目標(biāo)對(duì)象  
  7.     @PostConstruct  //③ 初始化方法  
  8.     private void setSelf() {  
  9.         //從上下文獲取代理對(duì)象(如果通過(guò)proxtSelf=this是不對(duì)的,this是目標(biāo)對(duì)象)  
  10.         //此種方法不適合于prototype Bean,因?yàn)槊看蝕etBean返回一個(gè)新的Bean  
  11.         proxySelf = context.getBean(AService.class);   
  12.     }  
  13.     @Transactional(propagation = Propagation.REQUIRED)  
  14.     public void a() {  
  15.        proxySelf.b(); //④ 調(diào)用代理對(duì)象的方法 這樣可以執(zhí)行事務(wù)切面  
  16.     }  
  17.     @Transactional(propagation = Propagation.REQUIRES_NEW)  
  18.     public void b() {  
  19.     }  
  20. }  

 

此處日志就不分析,和3.1類(lèi)似。此種方式不是很靈活,所有需要自我調(diào)用的實(shí)現(xiàn)類(lèi)必須重復(fù)實(shí)現(xiàn)代碼。



3.3、通過(guò)BeanPostProcessor 在目標(biāo)對(duì)象中注入代理對(duì)象


此種解決方案可以參考http://fyting./blog/109236。


 


BeanPostProcessor 的介紹和使用敬請(qǐng)等待我的下一篇分析帖。


 


一、定義BeanPostProcessor 需要使用的標(biāo)識(shí)接口


 


Java代碼 復(fù)制代碼 收藏代碼
  1. public interface BeanSelfAware {  
  2.     void setSelf(Object proxyBean);  
  3. }  

 即我們自定義的BeanPostProcessor InjectBeanSelfProcessor如果發(fā)現(xiàn)我們的Bean是實(shí)現(xiàn)了該標(biāo)識(shí)接口就調(diào)用setSelf注入代理對(duì)象。


 


二、Bean實(shí)現(xiàn)


Java代碼 復(fù)制代碼 收藏代碼
  1. @Service  
  2. public class AServiceImpl4 implements AService, BeanSelfAware {//此處省略接口定義  
  3.     private AService proxySelf;  
  4.     public void setSelf(Object proxyBean) { //通過(guò)InjectBeanSelfProcessor注入自己(目標(biāo)對(duì)象)的AOP代理對(duì)象  
  5.         this.proxySelf = (AService) proxyBean;  
  6.     }  
  7.     @Transactional(propagation = Propagation.REQUIRED)  
  8.     public void a() {  
  9.         proxySelf.b();//調(diào)用代理對(duì)象的方法 這樣可以執(zhí)行事務(wù)切面  
  10.     }  
  11.     @Transactional(propagation = Propagation.REQUIRES_NEW)  
  12.     public void b() {  
  13.     }  
  14. }   

實(shí)現(xiàn)BeanSelfAware標(biāo)識(shí)接口的setSelf將代理對(duì)象注入,并且通過(guò)“proxySelf.b()”這樣可以實(shí)施b方法的事務(wù)定義。


 


三、InjectBeanSelfProcessor實(shí)現(xiàn)


 


Java代碼 復(fù)制代碼 收藏代碼
  1. @Component  
  2. public class InjectBeanSelfProcessor implements BeanPostProcessor {  
  3.     public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {  
  4.         return bean;  
  5.     }  
  6.     public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {  
  7.         if(bean instanceof BeanSelfAware) {//如果Bean實(shí)現(xiàn)了BeanSelfAware標(biāo)識(shí)接口,就將代理對(duì)象注入  
  8.             ((BeanSelfAware) bean).setSelf(bean); //即使是prototype Bean也可以使用此種方式  
  9.         }  
  10.         return bean;  
  11.     }  
  12. }  

 

postProcessAfterInitialization根據(jù)目標(biāo)對(duì)象是否實(shí)現(xiàn)BeanSelfAware標(biāo)識(shí)接口,通過(guò)setSelf(bean)將代理對(duì)象(bean)注入到目標(biāo)對(duì)象中,從而可以完成目標(biāo)對(duì)象內(nèi)部的自我調(diào)用。


 


關(guān)于BeanPostProcessor的執(zhí)行流程等請(qǐng)一定參考我的這篇帖子,否則無(wú)法繼續(xù)往下執(zhí)行。


 


四、InjectBeanSelfProcessor的問(wèn)題


1、場(chǎng)景:通過(guò)InjectBeanSelfProcessor進(jìn)行注入代理對(duì)象且循環(huán)依賴(lài)場(chǎng)景下會(huì)產(chǎn)生前者無(wú)法通過(guò)setSelf設(shè)置代理對(duì)象的問(wèn)題。 循環(huán)依賴(lài)是應(yīng)該避免的,但是實(shí)際工作中不可避免會(huì)有人使用這種注入,畢竟沒(méi)有強(qiáng)制性。


 


2、用例


2.1、定義BeanPostProcessor 需要使用的標(biāo)識(shí)接口


3.1中一樣此處不再重復(fù)。


 


2.2、Bean實(shí)現(xiàn)


 


Java代碼 復(fù)制代碼 收藏代碼
  1. @Service  
  2. public class AServiceImpl implements AService, BeanSelfAware {//此處省略Aservice接口定義  
  3.     @Autowired  
  4.     private BService bService;   //①  通過(guò)@Autowired方式注入BService  
  5.     private AService self;       //②  注入自己的AOP代理對(duì)象  
  6.     public void setSelf(Object proxyBean) {  
  7.         this.self = (AService) proxyBean;  //③ 通過(guò)InjectBeanSelfProcessor注入自己(目標(biāo)對(duì)象)的AOP代理對(duì)象  
  8.         System.out.println("AService=="+ AopUtils.isAopProxy(this.self)); //如果輸出true標(biāo)識(shí)AOP代理對(duì)象注入成功  
  9.     }  
  10.     @Transactional(propagation = Propagation.REQUIRED)  
  11.     public void a() {  
  12.         self.b();  
  13.     }  
  14.     @Transactional(propagation = Propagation.REQUIRES_NEW)  
  15.     public void b() {  
  16.     }  
  17. }  

  


 


Java代碼 復(fù)制代碼 收藏代碼
  1. @Service  
  2. public class BServiceImpl implements BService, BeanSelfAware {//此處省略Aservice接口定義  
  3.     @Autowired  
  4.     private AService aService;  //①  通過(guò)@Autowired方式注入AService  
  5.     private BService self;      //②  注入自己的AOP代理對(duì)象  
  6.     public void setSelf(Object proxyBean) {  //③ 通過(guò)InjectBeanSelfProcessor注入自己(目標(biāo)對(duì)象)的AOP代理對(duì)象  
  7.         this.self = (BService) proxyBean;  
  8.         System.out.println("BService=" + AopUtils.isAopProxy(this.self)); //如果輸出true標(biāo)識(shí)AOP代理對(duì)象注入成功  
  9.     }  
  10.     @Transactional(propagation = Propagation.REQUIRED)  
  11.     public void a() {  
  12.         self.b();  
  13.     }  
  14.     @Transactional(propagation = Propagation.REQUIRES_NEW)  
  15.     public void b() {  
  16.     }  
  17. }  

此處A依賴(lài)B,B依賴(lài)A,即構(gòu)成循環(huán)依賴(lài),此處不探討循環(huán)依賴(lài)的設(shè)計(jì)問(wèn)題(實(shí)際工作應(yīng)該避免循環(huán)依賴(lài)),只探討為什么循環(huán)依賴(lài)會(huì)出現(xiàn)注入代理對(duì)象失敗的問(wèn)題。


 


循環(huán)依賴(lài)請(qǐng)參考我的博文【http://jinnianshilongnian./blog/1415278】。


依賴(lài)的初始化和銷(xiāo)毀順序請(qǐng)參考我的博文【http://jinnianshilongnian./blog/1415461】。


 


2.3、InjectBeanSelfProcessor實(shí)現(xiàn)


和之前3.3中一樣 此處不再重復(fù)。


 


2.4、測(cè)試用例


 


Java代碼 復(fù)制代碼 收藏代碼
  1. @RunWith(value = SpringJUnit4ClassRunner.class)  
  2. @ContextConfiguration(value = {"classpath:spring-config.xml"})  
  3. public class SelfInjectTest {  
  4.     @Autowired  
  5.     AService aService;  
  6.     @Autowired  
  7.     BService bService;  
  8.     @Test  
  9.     public void test() {  
  10.     }  
  11. }  

  

執(zhí)行如上測(cè)試用例會(huì)輸出:


BService=true


AService==false


BService通過(guò)InjectBeanSelfProcessor注入代理對(duì)象成功,而AService卻失敗了(實(shí)際是注入了目標(biāo)對(duì)象),如下是debug得到的信息:


 




 


 


2. 5、這是為什么呢,怎么在循環(huán)依賴(lài)會(huì)出現(xiàn)這種情況?


 


敬請(qǐng)期待我的下一篇分析帖。



3.4、改進(jìn)版的InjectBeanSelfProcessor的解決方案


Java代碼 復(fù)制代碼 收藏代碼
  1. @Component  
  2. public class InjectBeanSelfProcessor2 implements BeanPostProcessor, ApplicationContextAware {  
  3.     private ApplicationContext context;  
  4.     //① 注入ApplicationContext  
  5.     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {  
  6.         this.context = applicationContext;  
  7.     }  
  8.     public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {  
  9.         if(!(bean instanceof BeanSelfAware)) { //② 如果Bean沒(méi)有實(shí)現(xiàn)BeanSelfAware標(biāo)識(shí)接口 跳過(guò)  
  10.             return bean;  
  11.         }  
  12.         if(AopUtils.isAopProxy(bean)) { //③ 如果當(dāng)前對(duì)象是AOP代理對(duì)象,直接注入  
  13.             ((BeanSelfAware) bean).setSelf(bean);  
  14.         } else {  
  15.             //④ 如果當(dāng)前對(duì)象不是AOP代理,則通過(guò)context.getBean(beanName)獲取代理對(duì)象并注入  
  16.             //此種方式不適合解決prototype Bean的代理對(duì)象注入  
  17.             ((BeanSelfAware)bean).setSelf(context.getBean(beanName));  
  18.         }  
  19.         return bean;  
  20.     }  
  21.     public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {  
  22.         return bean;  
  23.     }  
  24. }  

 



5、總結(jié)


縱觀其上:


3.1 通過(guò)ThreadLocal暴露Aop代理對(duì)象】適合解決所有場(chǎng)景(不管是singleton Bean還是prototype Bean)的AOP代理獲取問(wèn)題(即能解決目標(biāo)對(duì)象的自我調(diào)用問(wèn)題);


 


3.2 通過(guò)初始化方法在目標(biāo)對(duì)象中注入代理對(duì)象】 和【3.4 改進(jìn)版的InjectBeanSelfProcessor的解決方案】能解決普通(無(wú)循環(huán)依賴(lài))的AOP代理對(duì)象注入問(wèn)題,而且也能解決【3.3】中提到的循環(huán)依賴(lài)(應(yīng)該是singleton之間的循環(huán)依賴(lài))造成的目標(biāo)對(duì)象無(wú)法注入AOP代理對(duì)象問(wèn)題,但該解決方案不適合解決循環(huán)依賴(lài)中包含prototype Bean的自我調(diào)用問(wèn)題;


 


3.3 通過(guò)BeanPostProcessor 在目標(biāo)對(duì)象中注入代理對(duì)象】:只能解決
普通(無(wú)循環(huán)依賴(lài))的 Bean注入AOP代理,無(wú)法解決循環(huán)依賴(lài)的AOP代理對(duì)象注入問(wèn)題,即無(wú)法解決目標(biāo)對(duì)象的自我調(diào)用問(wèn)題。


 


 


 


jingnianshilongnian 寫(xiě)道



spring允許的循環(huán)依賴(lài)(只考慮單例和原型Bean):
A----B
B----A
只有在A和B都不為原型是允許的,即如果A和B都是prototype則會(huì)報(bào)錯(cuò)(無(wú)法進(jìn)行原型Bean的循環(huán)依賴(lài))。
A(單例)---B(單例) 或 A(原型)---B(單例) 這是可以的,但 A(原型)---B(原型)或 A(原型)---B(單例Lazy)【且context.getBean("A")】時(shí) 這是不允許的。

一、A(原型)---B(原型) A(原型)---B(單例Lazy)【且context.getBean("A")】  會(huì)報(bào):
Error creating bean with name 'BServiceImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.sishuok.issue.AService com.sishuok.issue.impl.BServiceImpl.aService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'AServiceImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.sishuok.issue.BService com.sishuok.issue.impl.AServiceImpl.bService; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'BServiceImpl': Requested bean is currently in creation: [color=red]Is there an unresolvable circular reference[/color]?

二、A(原型)---B(單例) 和 A(單例)---B(單例)
這種方式 使用我的 【3.3 通過(guò)BeanPostProcessor 在目標(biāo)對(duì)象中注入代理對(duì)象】 是沒(méi)有問(wèn)題的。

因此【
3.4 改進(jìn)版的InjectBeanSelfProcessor的解決方案 】 可以作為最后的解決方案。

 

 


沒(méi)有完美的解決方案,只有最適用的解決方案。


 


測(cè)試代碼請(qǐng)參考附件,jar包與http://www./topic/1120924使用的是一樣的


 


下一篇  Spring開(kāi)閉原則的表現(xiàn)-BeanPostProcessor擴(kuò)展點(diǎn)-1


   

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多