 注:組件與組件之間的耦合,采用依賴注入管理,但普通的javaBean屬性值,應直接在代碼中設置。
注:組件與組件之間的耦合,采用依賴注入管理,但普通的javaBean屬性值,應直接在代碼中設置。
我們分析一下,Bean_A的一個屬性要依賴Bean_B的一個屬性值。這時應該怎么配,我們以前使用的都是通過setter方法來為Bean設置值,現在我們卻要使用getter方法來獲取Bean的屬性值。使用我們現在的知識完全可以解決這個問題(可以先不看下面的分析,對照Spring應用教程-1的第六節:Bean的生命周期自己分析 ):
):
①Bean_A的一個屬性要依賴Bean_B的一個屬性值,那么我們必須首先要獲取這個Bean,要獲取Bean,我就要實現BeanFactoryAware接口;
②獲取Bean_B的屬性值,那個屬性呢?這個值必須要在外面給我們說明,從Bean生命周期中我們除了發現BeanNameAware接口可以將外面的屬性名給我之外,再沒有其它合適的方法了。
③返回獲取的Bean_B的屬性值。由于我們是在Spring配置文件中配置這個信息,一般的Bean返回的是該Bean的實例,而我們現在要的是該bean的屬性值 ,這就使得我們必須實現FactoryBean接口了。
我們定義這樣一個實例,習大大有一個母親,名字叫中國,我也是,我要依賴他的母親屬性的值:
[+]view codepublicclass Chinese {
private China mother; public China getMother() { returnmother; } publicvoid setMother(China mother) { this.mother = mother; }}我創建一個Chinese類,他有一個類型為China的mother。然后我們創建一個工具類,實現我們的屬性值注入功能:
[+]view codepublicclass PropertyRefConfig implements BeanFactoryAware, BeanNameAware,
FactoryBean<Object> { private BeanFactory beanFactory=null; private String property=null; @Override publicvoid setBeanName(String beanName) { this.property=beanName; } @Override publicvoid setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory=beanFactory; } @Override public Object getObject() throws Exception { String[] paths=property.split("http://."); Object obj=beanFactory.getBean(paths[0]); Object tmp=obj; Class<?> type=obj.getClass(); for(int i=1; i<paths.length; i++){ String pro="get"+paths[i].replace(paths[i].charAt(0), String.valueOf(paths[i].charAt(0)).toUpperCase().charAt(0)); Method method=type.getMethod(pro); obj=method.invoke(obj); } return tmp==obj?null:obj; } @Override public Class<?> getObjectType() { // TODO Auto-generated method stub returnnull; } @Override publicboolean isSingleton() { // TODO Auto-generated method stub returnfalse; }}這個類配置為Bean后,在進行實例化并通過setter注入屬性后,執行BeanNameAware接口方法(setBeanName),通過該方法我們拿到了該Bean的id屬性,我們這里不是使用這個id屬性獲取該Bean的實例的,這個id已經失去了它本來的意義,我們是讓它把我們要的數據(那個Bean的那個屬性)給我們帶進來。然后解析這個id,獲取要獲取那個Bean和該Bean的屬性值。然后通過FactoryBean將該屬性值返回。
然后我們配置Bean,使我的mother屬性依賴習大大的mother屬性![X@8}U9MLE}EBUE273)]9PGF X@8}U9MLE}EBUE273)]9PGF](http://s1.VeVb.com/20150728/xjr3y0p43vn57.gif)
<beanid="china"class="smzq.China"/>
<beanid="xidada"class="smzq.Chinese"> <propertyname="mother"ref="china"/></bean><beanid="me"class="smzq.Chinese"> <propertyname="mother"> <beanid="xidada.mother"class="smzq.PropertyRefConfig"/> </property></bean>這里我們使用了嵌套Bean,它的id屬性表明,我們要取xidada的mother屬性。
測試:

其實這也就是PropertyPathFactoryBean的原理,不過強大的Spring將它包裝的更完美了![X@8}U9MLE}EBUE273)]9PGF X@8}U9MLE}EBUE273)]9PGF](http://s1.VeVb.com/20150728/1z0n5yfjkqs57.gif) 。有了這個類,我們便可以直接使用了,不用再費神的寫PropertyRefConfig了:
。有了這個類,我們便可以直接使用了,不用再費神的寫PropertyRefConfig了:
<beanid="china"class="smzq.China"/>
<beanid="xidada"class="smzq.Chinese"> <propertyname="mother"ref="china"/></bean><beanid="me"class="smzq.Chinese"> <propertyname="mother"> <beanid="xidada.mother"class="org.springframework.beans.factory.config.PropertyPathFactoryBean"/> </property></bean>這樣配置便好了。查看PropertyPathFactoryBean我們發現,它也是繼承了這3個接口:

按照前面的例子,我們可以輕松的自己實現這個功能,這里就不再演示了(反正又沒Spring寫得好 )直接用Spring提供的類了:
)直接用Spring提供的類了:
通過Spring提供的MethodInvokingFactoryBean工廠Bean便可以實現這個需求:
[+]view code<beanid="china"class="smzq.China"/>
<beanid="xidada"class="smzq.Chinese"> <propertyname="mother"ref="china"/></bean><beanid="me"class="smzq.Chinese"> <propertyname="mother"> <beanclass="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> <propertyname="targetObject"ref="xidada"/> <propertyname="targetMethod"value="getMother"/> </bean> </property></bean>其中:
targetObject屬性表明要調用那個Bean中的方法;
targetMethod屬性表明要調用那個方法。
上面我們調用的方法是實例方法,如果我們調用的是一個靜態方法時,就無需使用targetObject屬性了,使用targetClass屬性即可。
我們都知道,Java允許方法重載,那么我們上面這樣的調用遇見重載方法時是不是會出現問題呢?如果方法有參數,我們怎么傳入?
我們上面這種方法實際上是調用對應方法的無參版本,如果方法有參數,則使用arguments屬性來傳入:
[+]view code<beanid="commonpeople"class="smzq.People">
<propertyname="mustobserve"> <beanclass="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> <propertyname="targetObject"ref="chairman"/> <propertyname="targetMethod"value="enacted_laws"/> <propertyname="arguments"> <list> <value>憲法</value> <refbean="where"/> </list> </property> </bean> </property></bean>如果對給集合類型注入值不太熟悉的話,可以參考Spring應用教程-1的7.2節。
新聞熱點
疑難解答