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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

spring的bean定义真的和顺序无关?

發(fā)布時(shí)間:2024/4/17 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 spring的bean定义真的和顺序无关? 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

http://narcissusoyf.iteye.com/blog/705511

在使用Ibatis的時(shí)候,如果某個(gè)sql的定義出現(xiàn)在引用sql的定義之后的話,笨笨的ibatis是會(huì)報(bào)錯(cuò)的。。這讓用慣了spring的人會(huì)感到煩躁,為什么ibatis不能和spring一樣,做到xml定義的時(shí)候與順序無關(guān)。。。但是 spring 真的能夠做到完全與bean定義的順序無關(guān)么?下面的代碼,會(huì)讓我們警醒下:

Xml代碼 ?
  • <?xml?version="1.0"?encoding="UTF-8"?>??
  • <beans?xmlns="http://www.springframework.org/schema/beans"?? ??
  • ?????????xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"?? ??
  • ?????????xmlns:aop="http://www.springframework.org/schema/aop"?? ??
  • ?????????xmlns:tx="http://www.springframework.org/schema/tx"?? ??
  • ?????????xsi:schemaLocation="http://www.springframework.org/schema/beans?http://www.springframework.org/schema/beans/spring-beans-2.0.xsd??? ??
  • ???????????http://www.springframework.org/schema/aop?http://www.springframework.org/schema/aop/spring-aop-2.0.xsd??? ??
  • ???????????http://www.springframework.org/schema/tx?http://www.springframework.org/schema/tx/spring-tx-2.0.xsd" ??
  • ???????????default-autowire="byName">?? ??
  • ???<bean?id="a"?class="org.springframework.aop.framework.ProxyFactoryBean">??
  • ????????<property?name="target"?ref="targetA"?/>?? ??
  • ????????<property?name="interceptorNames">??
  • ????????????<list>??
  • ????????????????<value>beforeAdvisor</value>??
  • ????????????</list>??
  • ????????</property>??
  • ????</bean>??????? ??
  • ????<bean?id="targetA"?class="reference.A"></bean>?? ??
  • ????<bean?id="targetB"?class="reference.B"></bean>?? ??
  • ????<bean?id="beforeAdvice"?class="reference.BeforeAdvice"?/>??
  • ????<bean?id="beforeAdvisor"?class="reference.BeforeAdvisor">??
  • ????????<property?name="advice"?ref="beforeAdvice"/>??
  • ????</bean>??
  • ????<bean?id="b"?class="org.springframework.aop.framework.ProxyFactoryBean">??
  • ????????<property?name="target"?ref="targetB"?/>?? ??
  • ????????<property?name="interceptorNames">??
  • ????????????<list>??
  • ????????????????<value>beforeAdvisor</value>??
  • ????????????</list>??
  • ????????</property>??
  • ????</bean>??
  • </beans>??
  • <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"default-autowire="byName"> <bean id="a" class="org.springframework.aop.framework.ProxyFactoryBean"><property name="target" ref="targetA" /> <property name="interceptorNames"><list><value>beforeAdvisor</value></list></property></bean> <bean id="targetA" class="reference.A"></bean> <bean id="targetB" class="reference.B"></bean> <bean id="beforeAdvice" class="reference.BeforeAdvice" /><bean id="beforeAdvisor" class="reference.BeforeAdvisor"><property name="advice" ref="beforeAdvice"/></bean><bean id="b" class="org.springframework.aop.framework.ProxyFactoryBean"><property name="target" ref="targetB" /> <property name="interceptorNames"><list><value>beforeAdvisor</value></list></property></bean> </beans>

    ?一個(gè)簡(jiǎn)單的循環(huán)引用 + ProxyFactoryBean 定義。

    啟動(dòng)spring的代碼:

    Java代碼 ?
  • public?class?Main? ??
  • { ??
  • ????public?static?void?main(String[]?args)?throws?IOException ??
  • ????{ ??
  • ??
  • ????????ApplicationContext?ac?=?new?ClassPathXmlApplicationContext("/files/reference.xml"); ??
  • ????????InterfaceA?a?=?(InterfaceA)?ac.getBean("a"); ??
  • ????????a.ok(); ??
  • ????} ??
  • }??
  • public class Main {public static void main(String[] args) throws IOException{ApplicationContext ac = new ClassPathXmlApplicationContext("/files/reference.xml");InterfaceA a = (InterfaceA) ac.getBean("a");a.ok();} }

    ?接著就是悲劇的error:

    Java代碼 ?
  • Caused?by:?org.springframework.beans.factory.BeanCurrentlyInCreationException:?Error?creating?bean?with?name?'a':?org.springframework.beans.factory.FactoryBeanNotInitializedException:?Cannot?determine?target?class?for?proxy ??
  • ????at?org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:147) ??
  • ????at?org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:109) ??
  • ????at?org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1387) ??
  • ????at?org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:244) ??
  • ????at?org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:189) ??
  • ????at?org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireByName(AbstractAutowireCapableBeanFactory.java:1085) ??
  • ????at?org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1035) ??
  • ????at?org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511) ??
  • ????...?39?more??
  • Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'a': org.springframework.beans.factory.FactoryBeanNotInitializedException: Cannot determine target class for proxyat org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:147)at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:109)at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1387)at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:244)at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:189)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireByName(AbstractAutowireCapableBeanFactory.java:1085)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1035)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511)... 39 more

    ??好,那么我們換下bean定義的順序吧:

    Xml代碼 ?
  • <bean?id="targetA"?class="reference.A"></bean>?? ??
  • <bean?id="a"?class="org.springframework.aop.framework.ProxyFactoryBean">??
  • ????<property?name="target"?ref="targetA"?/>?? ??
  • ????<property?name="interceptorNames">??
  • ????????<list>??
  • ????????????<value>beforeAdvisor</value>??
  • ????????</list>??
  • ????</property>??
  • </bean>??? ??
  • <bean?id="targetB"?class="reference.B"></bean>?? ??
  • <bean?id="beforeAdvice"?class="reference.BeforeAdvice"?/>??
  • <bean?id="beforeAdvisor"?class="reference.BeforeAdvisor">??
  • ????<property?name="advice"?ref="beforeAdvice"/>??
  • </bean>??
  • <bean?id="b"?class="org.springframework.aop.framework.ProxyFactoryBean">??
  • ????<property?name="target"?ref="targetB"?/>?? ??
  • ????<property?name="interceptorNames">??
  • ????????<list>??
  • ????????????<value>beforeAdvisor</value>??
  • ????????</list>??
  • ????</property>??
  • </bean>??
  • <bean id="targetA" class="reference.A"></bean> <bean id="a" class="org.springframework.aop.framework.ProxyFactoryBean"><property name="target" ref="targetA" /> <property name="interceptorNames"><list><value>beforeAdvisor</value></list></property></bean> <bean id="targetB" class="reference.B"></bean> <bean id="beforeAdvice" class="reference.BeforeAdvice" /><bean id="beforeAdvisor" class="reference.BeforeAdvisor"><property name="advice" ref="beforeAdvice"/></bean><bean id="b" class="org.springframework.aop.framework.ProxyFactoryBean"><property name="target" ref="targetB" /> <property name="interceptorNames"><list><value>beforeAdvisor</value></list></property></bean>

    ?再run一次:

    Java代碼 ?
  • 2010-7-4?23:09:09?org.springframework.context.support.AbstractApplicationContext?prepareRefresh ??
  • 信息:?Refreshing?org.springframework.context.support.ClassPathXmlApplicationContext@32fb4f:?startup?date?[Sun?Jul?04?23:09:09?CST?2010];?root?of?context?hierarchy ??
  • 2010-7-4?23:09:09?org.springframework.beans.factory.xml.XmlBeanDefinitionReader?loadBeanDefinitions ??
  • 信息:?Loading?XML?bean?definitions?from?class?path?resource?[files/reference.xml] ??
  • 2010-7-4?23:09:09?org.springframework.beans.factory.support.DefaultListableBeanFactory?preInstantiateSingletons ??
  • 信息:?Pre-instantiating?singletons?in?org.springframework.beans.factory.support.DefaultListableBeanFactory@1d7ad1c:?defining?beans?[targetA,a,targetB,beforeAdvice,beforeAdvisor,b];?root?of?factory?hierarchy ??
  • xxx ??
  • $Proxy1??
  • 2010-7-4 23:09:09 org.springframework.context.support.AbstractApplicationContext prepareRefresh 信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@32fb4f: startup date [Sun Jul 04 23:09:09 CST 2010]; root of context hierarchy 2010-7-4 23:09:09 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions 信息: Loading XML bean definitions from class path resource [files/reference.xml] 2010-7-4 23:09:09 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons 信息: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1d7ad1c: defining beans [targetA,a,targetB,beforeAdvice,beforeAdvisor,b]; root of factory hierarchy xxx $Proxy1

    ?

    成功了。。。。。

    ?

    duo xi die ? 這是為什么呢?

    ?

    這里的問題確實(shí)是出在bean定義的順序上面。applicationContext 在refresh的時(shí)候,是按照bean定義的順序來加載singleton bean 的(除開BeanPostProcessor,BeanPostProcessor 在singleton加載之前被bean化)。如果僅僅只是加載普通的Bean或者普通的FactoryBean的話,Spring已經(jīng)通過某種方式很好的解決了singleton循環(huán)依賴的問題。

    ?

    導(dǎo)致這個(gè)問題的原因,是由2個(gè)原因疊加產(chǎn)生的:

    1??FactoryBean的getObject(),需要開發(fā)者自己去做處理。如果是new 個(gè)對(duì)象,那么這個(gè)對(duì)象就享受不到spring 的IOC 的好處,因?yàn)樗撾x了spring 容器的管轄。 而ProxyFactoryBean 的 getObject() 在獲取代理對(duì)象的時(shí)候,會(huì)對(duì)target的屬性有依賴,如果target的某些值為空,會(huì)拋錯(cuò)。(這里的target 通指 targetName,target)

    ?

    2 spring 再 bean化 bean的時(shí)候,是分為2步的,第一步可以簡(jiǎn)單的認(rèn)為new個(gè)對(duì)象出來,第二步為這個(gè)new出來的對(duì)象設(shè)置屬性。就是去容器里面把這個(gè)bean需要的其他bean給注入進(jìn)來。在第2步的時(shí)候,注入給其他的bean的bean 可能沒有被完全bean化,很有可能只是完成了第一步的bean,還是個(gè)“半成品”。但是在整個(gè)容器初始化結(jié)束的時(shí)候,這些“半成品”bean會(huì)被變成“合格品”。

    ?

    1 + 2 ,恩,就是ProxyFactoryBean在getObject()的時(shí)候,依賴了一個(gè)“半成品”,結(jié)果就悲劇了。

    Java代碼 ?
  • private?synchronized?Object?getSingletonInstance()?{ ??
  • ????if?(this.singletonInstance?==?null)?{ ??
  • ????????this.targetSource?=?freshTargetSource(); ??
  • ????????if?(this.autodetectInterfaces?&&?getProxiedInterfaces().length?==?0?&&?!isProxyTargetClass())?{ ??
  • ????????????//?Rely?on?AOP?infrastructure?to?tell?us?what?interfaces?to?proxy. ??
  • ????????????Class?targetClass?=?getTargetClass(); ??
  • ????????????if?(targetClass?==?null)?{ ??
  • ????????????????throw?new?FactoryBeanNotInitializedException("Cannot?determine?target?class?for?proxy"); ??
  • ????????????} ??
  • ????????????setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass,?this.proxyClassLoader)); ??
  • ????????} ??
  • ????????//?Initialize?the?shared?singleton?instance. ??
  • ????????super.setFrozen(this.freezeProxy); ??
  • ????????this.singletonInstance?=?getProxy(createAopProxy()); ??
  • ????} ??
  • ????return?this.singletonInstance; ??
  • }??
  • private synchronized Object getSingletonInstance() {if (this.singletonInstance == null) {this.targetSource = freshTargetSource();if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {// Rely on AOP infrastructure to tell us what interfaces to proxy.Class targetClass = getTargetClass();if (targetClass == null) {throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");}setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));}// Initialize the shared singleton instance.super.setFrozen(this.freezeProxy);this.singletonInstance = getProxy(createAopProxy());}return this.singletonInstance;}

    ?這里的targetSource 是ProxyFactoryBean 在設(shè)置target屬性的時(shí)候被設(shè)置進(jìn)去的,很可惜的是,這個(gè)時(shí)候的 target 指向的Bean?還在創(chuàng)建中,無法走到調(diào)用setTarget() 這一步。所以,這個(gè)時(shí)候的targetSource 就是個(gè) EMPTY_TARGET_SOURCE,它返回的targetClass? 就是null. 所以就失敗了。。。。

    ?

    原因找到了,那么怎么解決呢?

    解決也有2個(gè)方法,就是針對(duì)導(dǎo)致問題的2個(gè)原因作出處理么?

    A方案:

    針對(duì) ProxyFactoryBean 在getObject的時(shí)候,一定要求 targetSource的targetClass不為空,那么我就讓他fresh下吧。

    Xml代碼 ?
  • <?xml?version="1.0"?encoding="UTF-8"?>??
  • <beans?xmlns="http://www.springframework.org/schema/beans"?? ??
  • ?????????xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"?? ??
  • ?????????xmlns:aop="http://www.springframework.org/schema/aop"?? ??
  • ?????????xmlns:tx="http://www.springframework.org/schema/tx"?? ??
  • ?????????xsi:schemaLocation="http://www.springframework.org/schema/beans?http://www.springframework.org/schema/beans/spring-beans-2.0.xsd??? ??
  • ???????????http://www.springframework.org/schema/aop?http://www.springframework.org/schema/aop/spring-aop-2.0.xsd??? ??
  • ???????????http://www.springframework.org/schema/tx?http://www.springframework.org/schema/tx/spring-tx-2.0.xsd" ??
  • ???????????default-autowire="byName">?? ??
  • ??????? ??
  • ???? ??
  • ????<bean?id="a"?class="org.springframework.aop.framework.ProxyFactoryBean">??
  • ????????<property?name="targetName"?value="targetA"?/>???? ??
  • ????????<property?name="interceptorNames">??
  • ????????????<list>??
  • ????????????????<value>beforeAdvisor</value>??
  • ????????????</list>??
  • ????????</property>??
  • ????</bean>??? ??
  • ???? ??
  • ????<bean?id="targetA"?class="reference.A"></bean>?? ??
  • ????<bean?id="targetB"?class="reference.B"></bean>?? ??
  • ????<bean?id="beforeAdvice"?class="reference.BeforeAdvice"?/>??
  • ????<bean?id="beforeAdvisor"?class="reference.BeforeAdvisor">??
  • ????????<property?name="advice"?ref="beforeAdvice"/>??
  • ????</bean>??
  • ????<bean?id="b"?class="org.springframework.aop.framework.ProxyFactoryBean">??
  • ????????<property?name="targetName"?value="targetB"?/>???? ??
  • ????????<property?name="interceptorNames">??
  • ????????????<list>??
  • ????????????????<value>beforeAdvisor</value>??
  • ????????????</list>??
  • ????????</property>??
  • ????</bean>??
  • </beans>??
  • <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"default-autowire="byName"> <bean id="a" class="org.springframework.aop.framework.ProxyFactoryBean"><property name="targetName" value="targetA" /> <property name="interceptorNames"><list><value>beforeAdvisor</value></list></property></bean> <bean id="targetA" class="reference.A"></bean> <bean id="targetB" class="reference.B"></bean> <bean id="beforeAdvice" class="reference.BeforeAdvice" /><bean id="beforeAdvisor" class="reference.BeforeAdvisor"><property name="advice" ref="beforeAdvice"/></bean><bean id="b" class="org.springframework.aop.framework.ProxyFactoryBean"><property name="targetName" value="targetB" /> <property name="interceptorNames"><list><value>beforeAdvisor</value></list></property></bean> </beans>

    ?把 target,換成targetName 就可以了

    ?

    B方案:

    因?yàn)閟pring 在解決循環(huán)依賴的時(shí)候,化了個(gè)好大好大的圈,以至于我們需要的某個(gè)屬性遲遲還沒有set進(jìn)來。

    那么我們可以把這個(gè)大大的圈分成N個(gè)小小的圈嗎。。

    既然spring初始化singleton bean是從xml文件第一個(gè)bean開始的(除開BeanPostProcessor),那么我們就好好利用下這個(gè)第一個(gè)Bean么。。就把bean定義的位置給換下吧。。

    ?

    ?

    spring 還是和bean定義的順序有關(guān)的。希望大家在使用spring的時(shí)候,有所警醒。這個(gè)幾率的問題不是很大,在使用ProxyFactoryBean 的時(shí)候最好使用 targetName 屬性。另外,在使用FactoryBean的時(shí)候,需要借鑒下ProxyFactoryBean所導(dǎo)致的問題,對(duì)于某些屬性依賴的話,不要太相信spring會(huì)在那個(gè)時(shí)候給你設(shè)置進(jìn)去。

    ?

    總結(jié)

    以上是生活随笔為你收集整理的spring的bean定义真的和顺序无关?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。