javascript
Spring 管理Bean(获取Bean,初始化bean事件,自动匹配ByName······等)
1.實(shí)例化spring容器 和 從容器獲取Bean對(duì)象
實(shí)例化Spring容器常用的兩種方式:
方法一:
在類路徑下尋找配置文件來(lái)實(shí)例化容器 [推薦使用]
ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[]{"beans.xml"});
方法二:
在文件系統(tǒng)路徑下尋找配置文件來(lái)實(shí)例化容器 [這種方式可以在開(kāi)發(fā)階段使用]
ApplicationContext ctx = new FileSystemXmlApplicationContext(new String[]{“d:\\beans.xml“});
Spring的配置文件可以指定多個(gè),可以通過(guò)String數(shù)組傳入。
?
當(dāng)spring容器啟動(dòng)后,因?yàn)閟pring容器可以管理bean對(duì)象的創(chuàng)建,銷毀等生命周期,
所以我們只需從容器直接獲取Bean對(duì)象就行,而不用編寫一句代碼來(lái)創(chuàng)建bean對(duì)象。
從容器獲取bean對(duì)象的代碼如下:
ApplicationContext ctx = new ClassPathXmlApplicationContext(“beans.xml”);
OrderService service = (OrderService)ctx.getBean("personService");
?
2.Spring實(shí)例化Bean的三種方式
以下是三種方式的例子:
1.使用類構(gòu)造器實(shí)例化 [默認(rèn)的類構(gòu)造器] <bean id=“orderService" class="cn.itcast.OrderServiceBean"/>2.使用靜態(tài)工廠方法實(shí)例化 <bean id="personService" class="cn.itcast.service.OrderFactory" factory-method="createOrder"/> public class OrderFactory {public static OrderServiceBean createOrder(){ // 注意這里的這個(gè)方法是 static 的!return new OrderServiceBean();} }3.使用實(shí)例工廠方法實(shí)例化: <bean id="personServiceFactory" class="cn.itcast.service.OrderFactory"/> <bean id="personService" factory-bean="personServiceFactory" factory-method="createOrder"/> public class OrderFactory {public OrderServiceBean createOrder(){return new OrderServiceBean();} }?
3.Bean的生命周期 (Bean的作用域)
bean的scope 屬性
The scope of this bean: typically "singleton" (one shared instance, which will be returned by all calls?
to getBean with the given id), or "prototype" (independent instance resulting from each call to?
getBean).?Default is "singleton". Singletons are most commonly used, and are ideal for multi-?
threaded service objects.?Further scopes, such as "request" or "session", might be supported by?
extended bean factories (e.g. in a web environment).?Note: This attribute will not be inherited by?
child bean definitions.?Hence, it needs to be specified per concrete bean definition. Inner bean?
definitions inherit the singleton status of their containing bean definition, unless explicitly specified:?
The inner bean will be a singleton if the containing bean is a singleton, and a prototype if the?
containing bean has any other scope.
?
.singleton??[單例]?
eg:<bean id="personService" class="com.yinger.service.impl.PersonServiceBean" scope="singleton"></bean>
在每個(gè)Spring IoC容器中一個(gè)bean定義只有一個(gè)對(duì)象實(shí)例。
請(qǐng)注意Spring的singleton bean概念與“四人幫”(GoF)模式一書中定義的Singleton模式是完全不同的。
經(jīng)典的GoF Singleton模式中所謂的對(duì)象范圍是指在每一個(gè)ClassLoader中指定class創(chuàng)建的實(shí)例有且僅有一個(gè)。
把Spring的singleton作用域描述成一個(gè)container對(duì)應(yīng)一個(gè)bean實(shí)例最為貼切。亦即,假如在單個(gè)Spring容器內(nèi)定義了某個(gè)指定class的bean,
那么Spring容器將會(huì)創(chuàng)建一個(gè)且僅有一個(gè)由該bean定義指定的類實(shí)例。
?
默認(rèn)情況下會(huì)在容器啟動(dòng)時(shí)初始化bean,但我們可以指定Bean節(jié)點(diǎn)的lazy-init=“true”來(lái)延遲初始化bean,這時(shí)候,只有第一次獲取bean會(huì)才初始化bean。
如:<bean id="xxx" class="cn.itcast.OrderServiceBean"?lazy-init="true"/>
如果想對(duì)所有bean都應(yīng)用延遲初始化,可以在根節(jié)點(diǎn)beans設(shè)置default-lazy-init=“true“,如下:
<beans default-lazy-init="true“ ...>
.prototype?[原型]
每次從容器獲取bean都是新的對(duì)象。
對(duì)于prototype作用域的bean,有一點(diǎn)非常重要,那就是Spring不能對(duì)一個(gè)prototype bean的整個(gè)生命周期負(fù)責(zé):容器在初始化、配置、裝飾或者是
裝配完一個(gè)prototype實(shí)例后,將它交給客戶端,隨后就對(duì)該prototype實(shí)例不聞不問(wèn)了。不管何種作用域,容器都會(huì)調(diào)用所有對(duì)象的初始化生命周期回調(diào)方法。
但對(duì)prototype而言,任何配置好的析構(gòu)生命周期回調(diào)方法都將不會(huì)被調(diào)用。清除prototype作用域的對(duì)象并釋放任何prototype bean所持有的昂貴資源,
都是客戶端代碼的職責(zé)。(讓Spring容器釋放被prototype作用域bean占用資源的一種可行方式是,通過(guò)使用bean的后置處理器,該處理器持有要被清除的bean的引用。)
以下的三種scope只是在web應(yīng)用中才可以使用
.request
.session
.global session
使用這三種配置之前要先初始化Web配置
?
RequestContextListener和RequestContextFilter兩個(gè)類做的都是同樣的工作: 將HTTP request對(duì)象綁定到為該請(qǐng)求提供服務(wù)的Thread。
這使得具有request和session作用域的bean能夠在后面的調(diào)用鏈中被訪問(wèn)到。
?
指定Bean的初始化方法和銷毀方法
<bean id="xxx" class="cn.itcast.OrderServiceBean"?init-method="init" destroy-method="close"/>
Spring提供了幾個(gè)標(biāo)志接口(marker interface),這些接口用來(lái)改變?nèi)萜髦衎ean的行為;它們包括InitializingBean和DisposableBean。
現(xiàn)這兩個(gè)接口的bean在初始化和析構(gòu)時(shí)容器會(huì)調(diào)用前者的afterPropertiesSet()方法,以及后者的destroy()方法。
Spring在內(nèi)部使用BeanPostProcessor實(shí)現(xiàn)來(lái)處理它能找到的任何標(biāo)志接口并調(diào)用相應(yīng)的方法。
如果你需要自定義特性或者生命周期行為,你可以實(shí)現(xiàn)自己的?BeanPostProcessor。
初始化回調(diào)和析構(gòu)回調(diào):
?
測(cè)試:
bean對(duì)象:
package com.yinger.service.impl;public class PersonServiceBean implements com.yinger.service.PersonService{//構(gòu)造器public PersonServiceBean(){System.out.println("instance me");}//save方法public void save() {System.out.println("save");}//初始化方法,這個(gè)方法是類被實(shí)例化了之后就會(huì)執(zhí)行的!public void init(){System.out.println("init");}//銷毀方法public void destroy(){System.out.println("destroy");}}?
JUnit Test:
package com.yinger.test;import org.junit.BeforeClass; import org.junit.Test; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;import com.yinger.service.PersonService;public class SpringTest {@BeforeClasspublic static void setUpBeforeClass() throws Exception {}@Test //創(chuàng)建的單元測(cè)試public void testSave() {AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");System.out.println("--------");PersonService ps = (PersonService)ctx.getBean("personService");ps.save();ctx.close(); //有了這一句才會(huì)有destroy方法的調(diào)用}}beans.xml 設(shè)置:
如果lazy-init(默認(rèn)是default,也就是false)沒(méi)有設(shè)置,或者設(shè)置為default或者false
<bean id="personService" class="com.yinger.service.impl.PersonServiceBean"scope="singleton" init-method="init" destroy-method="destroy"lazy-init="false"></bean>那么結(jié)果是:
log4j:WARN No appenders could be found for logger (org.springframework.context.support.ClassPathXmlApplicationContext). log4j:WARN Please initialize the log4j system properly. instance me init -------- save destroy反之,如果設(shè)置為true,結(jié)果是:
log4j:WARN No appenders could be found for logger (org.springframework.context.support.ClassPathXmlApplicationContext). log4j:WARN Please initialize the log4j system properly. -------- instance me init save destroy?
修改測(cè)試代碼:
@Testpublic void testSave() {AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); // System.out.println("--------");PersonService ps = (PersonService)ctx.getBean("personService");PersonService ps1 = (PersonService)ctx.getBean("personService");System.out.println(ps==ps1); // ps.save();ctx.close();}
重新測(cè)試:
log4j:WARN No appenders could be found for logger (org.springframework.context.support.ClassPathXmlApplicationContext). log4j:WARN Please initialize the log4j system properly. instance me init true destroy[在scope為singleton時(shí),每次使用getBean得到的都是同一個(gè)bean,同一個(gè)對(duì)象]
修改bean中的scope屬性:scope="prototype"
測(cè)試結(jié)果:
log4j:WARN No appenders could be found for logger (org.springframework.context.support.ClassPathXmlApplicationContext). log4j:WARN Please initialize the log4j system properly. instance me init instance me init false[在scope為prototype時(shí),每次得到的bean對(duì)象都是不同的,從上面可以看出實(shí)例化了兩個(gè)對(duì)象,最終的比較是false]
?
4.依賴注入
來(lái)自Spring參考文檔:依賴注入(DI)背后的基本原理是對(duì)象之間的依賴關(guān)系(即一起工作的其它對(duì)象)只會(huì)通過(guò)以下幾種方式來(lái)實(shí)現(xiàn):構(gòu)造器的參數(shù)、工廠方法的參數(shù),
或給由構(gòu)造函數(shù)或者工廠方法創(chuàng)建的對(duì)象設(shè)置屬性。因此,容器的工作就是創(chuàng)建bean時(shí)注入那些依賴關(guān)系。
相對(duì)于由bean自己來(lái)控制其實(shí)例化、直接在構(gòu)造器中指定依賴關(guān)系或者類似服務(wù)定位器(Service Locator)模式這3種自主控制依賴關(guān)系注入的方法來(lái)說(shuō),
控制從根本上發(fā)生了倒轉(zhuǎn),這也正是控制反轉(zhuǎn)(Inversion of Control, IoC)?名字的由來(lái)。
?
(1)基本類型的注入:
基本類型對(duì)象注入: <bean id="orderService" class="cn.itcast.service.OrderServiceBean"><constructor-arg index=“0” type=“java.lang.String” value=“xxx”/>//構(gòu)造器注入<property name=“name” value=“zhao/>//屬性setter方法注入 </bean>注入其他bean:方式一 <bean id="orderDao" class="cn.itcast.service.OrderDaoBean"/> <bean id="orderService" class="cn.itcast.service.OrderServiceBean"><property name="orderDao" ref="orderDao"/> </bean>方式二(使用內(nèi)部bean,但該bean不能被其他bean使用) <bean id="orderService" class="cn.itcast.service.OrderServiceBean"><property name="orderDao"><bean class="cn.itcast.service.OrderDaoBean"/></property> </bean>?
測(cè)試 構(gòu)造器和setter 方式注入:
新建一個(gè)DAO的接口:
package com.yinger.dao;public interface PersonDao {public void save();}
新建一個(gè)接口的實(shí)現(xiàn)類:
package com.yinger.dao.impl;import com.yinger.dao.PersonDao;public class PersonDaoBean implements PersonDao{public void save() {System.out.println("PersonDaoBean.save()");}}
修改原有的PersonServiceBean,添加兩個(gè)字段:
package com.yinger.service.impl;import com.yinger.dao.PersonDao; import com.yinger.service.PersonService;public class PersonServiceBean implements PersonService{private PersonDao pDao;//這樣設(shè)計(jì)就實(shí)現(xiàn)了業(yè)務(wù)層和數(shù)據(jù)層的徹底解耦private String name;//默認(rèn)的構(gòu)造器public PersonServiceBean(){System.out.println("instance me");}//帶參數(shù)的構(gòu)造器public PersonServiceBean(PersonDao pDao){this.pDao=pDao;}//帶參數(shù)的構(gòu)造器public PersonServiceBean(PersonDao pDao,String name){this.pDao=pDao;this.name=name;}//save方法public void save() { // System.out.println("save");pDao.save();System.out.println(this.getName());}//初始化方法,這個(gè)方法是類被實(shí)例化了之后就會(huì)執(zhí)行的!public void init(){System.out.println("init");}//銷毀方法public void destroy(){System.out.println("destroy");}public String getName() {return name;}public void setName(String name) {this.name = name;}}
修改beans.xml:
<bean id="personService" class="com.yinger.service.impl.PersonServiceBean"><constructor-arg index="0"><bean id="pDao" class="com.yinger.dao.impl.PersonDaoBean"></bean></constructor-arg><constructor-arg index="1" type="java.lang.String" value="name" /></bean>
新增一個(gè)測(cè)試方法:
@Testpublic void testInjection() {AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");System.out.println("--------");PersonService ps = (PersonService)ctx.getBean("personService");ps.save();ctx.close();}
測(cè)試結(jié)果:
log4j:WARN No appenders could be found for logger (org.springframework.context.support.ClassPathXmlApplicationContext). log4j:WARN Please initialize the log4j system properly. -------- PersonDaoBean.save() name?
如果在beans.xml中再添加一句:
<property name="name" value="name2"></property>
重新測(cè)試,結(jié)果是:
log4j:WARN No appenders could be found for logger (org.springframework.context.support.ClassPathXmlApplicationContext). log4j:WARN Please initialize the log4j system properly. -------- PersonDaoBean.save() name2?
(2)集合類型的注入:
集合類型的裝配:
public class OrderServiceBean {private Set<String> sets = new HashSet<String>();private List<String> lists = new ArrayList<String>();private Properties properties = new Properties();private Map<String, String> maps = new HashMap<String, String>();....//這里省略屬性的getter和setter方法 }
XML配置:
<bean id="order" class="cn.itcast.service.OrderServiceBean"><property name="lists"><list><value>lihuoming</value></list></property> <property name="sets"><set><value>set</value></set></property> <property name="maps"><map><entry key="lihuoming" value="28"/></map></property> <property name="properties"><props><prop key="12">sss</prop></props></property> </bean>
?
補(bǔ)充:Spring對(duì)泛型的支持
?
(3)三種依賴注入的方式 和 兩種裝配方式:
①使用構(gòu)造器注入
②使用屬性setter方法注入:
通過(guò)調(diào)用無(wú)參構(gòu)造器或無(wú)參static工廠方法實(shí)例化bean之后,調(diào)用該bean的setter方法,即可實(shí)現(xiàn)基于setter的DI。
Spring開(kāi)發(fā)團(tuán)隊(duì)提倡使用setter注入。而且setter DI在以后的某個(gè)時(shí)候還可將實(shí)例重新配置(或重新注入)
③使用Field注入(用于注解方式)
?
處理bean依賴關(guān)系通常按以下步驟進(jìn)行:
根據(jù)定義bean的配置(文件)創(chuàng)建并初始化BeanFactory實(shí)例(大部份的Spring用戶使用支持XML格式配置文件的BeanFactory或ApplicationContext實(shí)現(xiàn))。
每個(gè)bean的依賴將以屬性、構(gòu)造器參數(shù)、或靜態(tài)工廠方法參數(shù)的形式出現(xiàn)。當(dāng)這些bean被實(shí)際創(chuàng)建時(shí),這些依賴也將會(huì)提供給該bean。
每個(gè)屬性或構(gòu)造器參數(shù)既可以是一個(gè)實(shí)際的值,也可以是對(duì)該容器中另一個(gè)bean的引用。
每個(gè)指定的屬性或構(gòu)造器參數(shù)值必須能夠被轉(zhuǎn)換成特定的格式或構(gòu)造參數(shù)所需的類型。默認(rèn)情況下,Spring會(huì)以String類型提供值轉(zhuǎn)換成各種內(nèi)置類型,?
比如int、long、String、boolean等。
?
在<constructor-arg/>或<property/>元素內(nèi)部還可以使用ref元素。該元素用來(lái)將bean中指定屬性的值設(shè)置為對(duì)容器中的另外一個(gè)bean的引用。
注意:內(nèi)部bean中的scope標(biāo)記及id或name屬性將被忽略。內(nèi)部bean總是匿名的且它們總是prototype模式的。同時(shí)將內(nèi)部bean注入到包含該內(nèi)部bean之外的bean是不可能的。
?
注入依賴對(duì)象可以采用手工裝配或自動(dòng)裝配,在實(shí)際應(yīng)用中建議使用手工裝配,因?yàn)樽詣?dòng)裝配會(huì)產(chǎn)生未知情況,開(kāi)發(fā)人員無(wú)法預(yù)見(jiàn)最終的裝配結(jié)果。
1.手工裝配依賴對(duì)象
2.自動(dòng)裝配依賴對(duì)象
?
<1>手工裝配
手工裝配依賴對(duì)象,在這種方式中又有兩種編程方式
1. 在xml配置文件中,通過(guò)在bean節(jié)點(diǎn)下配置,如
<bean id="orderService" class="cn.itcast.service.OrderServiceBean"><constructor-arg index=“0” type=“java.lang.String” value=“xxx”/>//構(gòu)造器注入<property name=“name” value=“zhao”/>//屬性setter方法注入</bean>2. 在java代碼中使用@Autowired或@Resource注解方式進(jìn)行裝配。但我們需要在xml配置文件中配置以下信息:
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"//注意這里,要添加的,還有下面的兩個(gè)紅色部分xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-2.5.xsd"><context:annotation-config/> </beans>這個(gè)配置隱式注冊(cè)了多個(gè)對(duì)注釋進(jìn)行解析處理的處理器:AutowiredAnnotationBeanPostProcessor,
CommonAnnotationBeanPostProcessor,PersistenceAnnotationBeanPostProcessor,RequiredAnnotationBeanPostProcessor
注:?@Resource注解在spring安裝目錄的lib\j2ee\common-annotations.jar
?
* 注解方式的講解
在java代碼中使用@Autowired或@Resource注解方式進(jìn)行裝配,這兩個(gè)注解的區(qū)別是:@Autowired 默認(rèn)按類型裝配,@Resource默認(rèn)按名稱裝配,當(dāng)找不到與名稱匹配的bean才會(huì)按類型裝配。@Autowired private PersonDao personDao;//用于字段上@Autowiredpublic void setOrderDao(OrderDao orderDao) {//用于屬性的setter方法上this.orderDao = orderDao;} @Autowired注解是按類型裝配依賴對(duì)象,默認(rèn)情況下它要求依賴對(duì)象必須存在,如果允許null值,可以設(shè)置它required屬性為false。如果我們想使用按名稱裝配,可以結(jié)合@Qualifier注解一起使用。如下:@Autowired @Qualifier("personDaoBean")private PersonDao personDao;注:@Autowired 注解可以使用在很多地方,包括了 集合類型,Map,來(lái)自ApplicationContext的特殊類型的所有 beans等等特殊的情況:多個(gè)構(gòu)造器雖然當(dāng) 一個(gè)類只有一個(gè)連接構(gòu)造器時(shí)它將被標(biāo)記為 required, 但是還是可以標(biāo)記多個(gè)構(gòu)造器的。在這種情況下,每一個(gè)構(gòu)造器都有可能被認(rèn)為是連接構(gòu)造器, Spring 將會(huì)把依賴關(guān)系能夠滿足的構(gòu)造器認(rèn)為是greediest 的構(gòu)造器??測(cè)試:@Autowired注解 [如果兩個(gè)構(gòu)造器都使用了該注解會(huì)報(bào)錯(cuò)!所以,在多個(gè)構(gòu)造器的情況下,要多多考慮]新建一個(gè)PersonServiceBean2類:其中有三處使用了 @Autowired注解 ,只要其中一個(gè)位置包含了注解就行[測(cè)試時(shí)]package com.yinger.service.impl;import org.springframework.beans.factory.annotation.Autowired;import com.yinger.dao.PersonDao; import com.yinger.service.PersonService;public class PersonServiceBean2 implements PersonService{//Autowired默認(rèn)是按照類型來(lái)裝配,這里是放在字段上@Autowired private PersonDao pDao;//這樣設(shè)計(jì)就實(shí)現(xiàn)了業(yè)務(wù)層和數(shù)據(jù)層的徹底解耦//默認(rèn)的構(gòu)造器public PersonServiceBean2(){System.out.println("instance me");}//帶參數(shù)的構(gòu)造器@Autowired //放在構(gòu)造方法上public PersonServiceBean2(PersonDao pDao){this.pDao=pDao;}//save方法public void save() {pDao.save();}//初始化方法,這個(gè)方法是類被實(shí)例化了之后就會(huì)執(zhí)行的!public void init(){System.out.println("init");}//銷毀方法public void destroy(){System.out.println("destroy");}public PersonDao getpDao() {return pDao;}@Autowired //放在屬性的setter上public void setpDao(PersonDao pDao) {this.pDao = pDao;}}?beans.xml: <context:annotation-config/><bean id="personService2" class="com.yinger.service.impl.PersonServiceBean2"></bean><bean id="personDao" class="com.yinger.dao.impl.PersonDaoBean"></bean>
測(cè)試方法:
@Test //用于測(cè)試依賴注入的方法public void testInjection() {AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");System.out.println("--------");PersonService ps = (PersonService)ctx.getBean("personService2");ps.save();ctx.close();}
測(cè)試結(jié)果:
log4j:WARN No appenders could be found for logger (org.springframework.context.support.ClassPathXmlApplicationContext). log4j:WARN Please initialize the log4j system properly. -------- PersonDaoBean.save()?
從結(jié)果中可以看出,PersonDao是注入進(jìn)去了!
[還有一個(gè)要注意,按照類型查找,并不是類型一定要完全吻合,可以是屬性(字段,方法參數(shù))的實(shí)現(xiàn)類(如果以上的是接口),上面的實(shí)例就是一個(gè)例子]
?@Resource注解和@Autowired一樣,也可以標(biāo)注在字段或?qū)傩缘膕etter方法上,但它默認(rèn)按名稱裝配。名稱可以通過(guò)@Resource的name屬性指定,如果沒(méi)有指定name屬性,當(dāng)注解標(biāo)注在字段上,即默認(rèn)取字段的名稱作為bean名稱尋找依賴對(duì)象,當(dāng)注解標(biāo)注在屬性的setter方法上,即默認(rèn)取屬性名作為bean名稱尋找依賴對(duì)象。 [推薦使用的方式]@Resource(name=“personDaoBean”)private PersonDao personDao;//用于字段上注意:如果沒(méi)有指定name屬性,并且按照默認(rèn)的名稱仍然找不到依賴對(duì)象時(shí), @Resource注解會(huì)回退到按類型裝配。但一旦指定了name屬性,就只能按名稱裝配了。?
測(cè)試: 測(cè)試時(shí)使用下面的一個(gè)注解就可以了
新建類PersonServiceBean3:
package com.yinger.service.impl;import javax.annotation.Resource;import com.yinger.dao.PersonDao; import com.yinger.service.PersonService;public class PersonServiceBean3 implements PersonService{//Resource默認(rèn)是按照名稱來(lái)裝配,這里是放在字段上@Resource private PersonDao pDao;//這樣設(shè)計(jì)就實(shí)現(xiàn)了業(yè)務(wù)層和數(shù)據(jù)層的徹底解耦//默認(rèn)的構(gòu)造器public PersonServiceBean3(){System.out.println("instance me");}//帶參數(shù)的構(gòu)造器public PersonServiceBean3(PersonDao pDao){this.pDao=pDao;}//save方法public void save() {pDao.save();}//初始化方法,這個(gè)方法是類被實(shí)例化了之后就會(huì)執(zhí)行的!public void init(){System.out.println("init");}//銷毀方法public void destroy(){System.out.println("destroy");}public PersonDao getpDao() {return pDao;}@Resource //放在屬性的setter上public void setpDao(PersonDao pDao) {this.pDao = pDao;}}?
beans.xml中的配置:
<context:annotation-config/><bean id="personService3" class="com.yinger.service.impl.PersonServiceBean3"></bean><bean id="pDao" class="com.yinger.dao.impl.PersonDaoBean"></bean>
測(cè)試結(jié)果:
log4j:WARN No appenders could be found for logger (org.springframework.context.support.ClassPathXmlApplicationContext). log4j:WARN Please initialize the log4j system properly. instance me -------- PersonDaoBean.save()?
注:beans.xml中第二個(gè)bean的id也可以是其他的名稱,例如personDao,同樣是上面的結(jié)果,因?yàn)?/p>
如果沒(méi)有指定name屬性,并且按照默認(rèn)的名稱仍然找不到依賴對(duì)象時(shí), @Resource注解會(huì)回退到按類型裝配。
?
<2>自動(dòng)裝配:
對(duì)于自動(dòng)裝配,大家了解一下就可以了,實(shí)在不推薦大家使用。例子:
<bean id="..." class="..."?autowire="byType"/>
autowire屬性取值如下:
byType:按類型裝配,可以根據(jù)屬性的類型,在容器中尋找跟該類型匹配的bean。如果發(fā)現(xiàn)多個(gè),那么將會(huì)拋出異常。如果沒(méi)有找到,即屬性值為null。
byName:按名稱裝配,可以根據(jù)屬性的名稱,在容器中尋找跟該屬性名相同的bean,如果沒(méi)有找到,即屬性值為null。
constructor與byType的方式類似,不同之處在于它應(yīng)用于構(gòu)造器參數(shù)。如果在容器中沒(méi)有找到與構(gòu)造器參數(shù)類型一致的bean,那么將會(huì)拋出異常。
autodetect:通過(guò)bean類的自省機(jī)制(introspection)來(lái)決定是使用constructor還是byType方式進(jìn)行自動(dòng)裝配。如果發(fā)現(xiàn)默認(rèn)的構(gòu)造器,那么將使用byType方式。
你也可以針對(duì)單個(gè)bean設(shè)置其是否為被自動(dòng)裝配對(duì)象。當(dāng)采用XML格式配置bean時(shí),<bean/>元素的?autowire-candidate屬性可被設(shè)為false,這樣容器在查找自動(dòng)裝配對(duì)象時(shí)將不考慮該bean。
?
5. 通過(guò)在classpath自動(dòng)掃描方式把組件納入spring容器中管理
前面的例子我們都是使用XML的bean定義來(lái)配置組件。在一個(gè)稍大的項(xiàng)目中,通常會(huì)有上百個(gè)組件,如果這些這組件采用xml的bean定義來(lái)配置,
顯然會(huì)增加配置文件的體積,查找及維護(hù)起來(lái)也不太方便。spring2.5為我們引入了組件自動(dòng)掃描機(jī)制,他可以在類路徑底下尋找標(biāo)注了@Component、
@Service、@Controller、@Repository注解的類,并把這些類納入進(jìn)spring容器中管理。
它的作用和在xml文件中使用bean節(jié)點(diǎn)配置組件是一樣的。要使用自動(dòng)掃描機(jī)制,我們需要打開(kāi)以下配置信息:
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-2.5.xsd"><context:component-scan base-package="cn.itcast"/> </beans>其中base-package為需要掃描的包(含子包)。
@Service用于標(biāo)注業(yè)務(wù)層組件、 @Controller用于標(biāo)注控制層組件(如struts中的action)、@Repository用于標(biāo)注數(shù)據(jù)訪問(wèn)組件,即DAO組件。而@Component泛指組件,當(dāng)組件不好歸類的時(shí)候,我們可以使用這個(gè)注解進(jìn)行標(biāo)注。
?
測(cè)試:
在上面的例子中,添加如下內(nèi)容:
@Service("personService3") public class PersonServiceBean3 implements PersonService{@Repository public class PersonDaoBean implements PersonDao{
同時(shí),在beans.xml中添加:
<context:component-scan base-package="com.yinger.dao.impl"></context:component-scan><context:component-scan base-package="com.yinger.service.impl"></context:component-scan>
測(cè)試方法不變,結(jié)果還是一樣:
log4j:WARN No appenders could be found for logger (org.springframework.context.support.ClassPathXmlApplicationContext). log4j:WARN Please initialize the log4j system properly. instance me -------- PersonDaoBean.save()轉(zhuǎn)載于:https://www.cnblogs.com/4wei/archive/2012/12/25/2847238.html
總結(jié)
以上是生活随笔為你收集整理的Spring 管理Bean(获取Bean,初始化bean事件,自动匹配ByName······等)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Windows批处理学习(二)——批处理
- 下一篇: [邻接表] 学习邻接表的表示方法+BFS