Spring之Bean的注入
Bean的配置中介紹的是Bean宣告問題,在哪宣告怎麼宣告的問題。Bean的注入是怎麼例項化,怎麼注入的問題。Bean注入的方式有兩種,一種是在XML中配置,另一種則是使用註解的方式注入。
一、XML方式注入
XML方式注入一般有三種方式:屬性注入、建構函式注入和工廠方法注入。
一、屬性注入
在傳統的物件例項化時可以通過new class(),然後通過setXXX()方法設定物件的屬性值或依賴物件,屬性注入也是採用這種方式,只是Spring框架會在內部完成這些操作,它會先呼叫Bean的預設建構函式例項化Bean物件,然後通過反射的方式呼叫Setter方法注入屬性值。它會使用預設的建構函式(無引數建構函式),只需為注入的屬性設定set方法,可選擇性和靈活性比較高,所以也是比較常用的一種注入方式。這裡示例還是在IOC章節使用人和空氣的基礎上稍作修改來演示。IAir介面和CleanAir、DirtyAir類不變,這裡就不貼了。
1.新建XMLInstance類
package com.demo.model; public class XMLInstance { private String name; public void setName(String name) { this.name = name; } private IAir air; public void setAir(IAir air) { this.air = air; } public void Breath() { System.out.println(View Code"Name:"+this.name+";Air:"+this.air.toString()); } public XMLInstance(String name, IAir air) { super(); this.name = name; this.air = air; } public XMLInstance() { } public void DestoryMethod() { System.out.println("DestoryMethod"); }public void InitMethod() { System.out.println("InitMethod"); } }
在XMLInstance類中並未宣告建構函式,對於air屬性只設置了set方法,get方法也沒設定。
<bean id="CleanAir" class="com.demo.model.CleanAir"> <qualifier value="cleanair"/> </bean> <bean id="xmlinstance" class="com.demo.model.XMLInstance"> <property name="air" ref="CleanAir"></property> <property name="name" value="abc"></property> </bean>
Xml中使用property類配置屬性,name是屬性名,value用來設定基本資料型別的屬性值。Spring配置檔案中bean之間可以相互引用,引用時可以用<ref>標籤配置bean的id屬性使用。<ref>可以用在<property>屬性中,也可以用在<construct-arg>建構函式的引數值,還可以用在其他地方,通過引用能減少bean的宣告。
二、建構函式注入
在屬性注入時先使用預設的建構函式(無引數建構函式)例項化,然後通過set方法注入屬性,在傳統例項化物件時可以自定義建構函式進行例項化,建構函式注入就是通過自定義建構函式來進行物件的例項化。這裡在XMLInstance類的基礎上增加了一個建構函式,第一個引數是String型別的name,第二個引數是IAir型別的air。
public XMLInstance(String name, IAir air) { super(); this.name = name; this.air = air; }
Xml中使用使用<construect-arg>來設定建構函式的引數,index屬性設定引數的順序,引數順序應該與建構函式的一致,ref設定引用bean的id,value設定建構函式引數的值。
<bean id="xmlcontructinstance" class="com.demo.model.XMLInstance"> <constructor-arg index="1" ref="CleanAir"></constructor-arg> <constructor-arg index="0" value="abc"></constructor-arg> </bean>
三、工廠方法注入
工廠方法注入參考的是工廠設計模式,通過在工廠類中實現物件的例項化。工廠類負責建立一個或多個目標類例項,工廠類方法一般以介面或抽象類變數的形式返回目標類例項,工廠類對外遮蔽了目標類的例項化步驟,呼叫者甚至不用知道具體的目標類是什麼。工廠方法也分靜態工廠方法和非靜態工廠方法,靜態工廠方式不用例項化工廠類,直接通過類名呼叫,非靜態工廠方法需要先例項化工廠類,然後通過工廠類物件呼叫獲取物件。這裡建立了一個工廠類XMLFactory,在類中定義了一個靜態方法,和一個例項方法用來例項化bean物件。
package com.demo.model; public class XMLFactory { public XMLInstance CreateInstance() { return new XMLInstance("instance",new CleanAir()); } public static XMLInstance CreateStaticInstance() { return new XMLInstance("static instance",new CleanAir()); } }
1.靜態工廠方法
只需設定工廠方法對應的類,以及對應的工廠方法。
<bean id="xmlfactorystaticinstance" class="com.demo.model.XMLFactory" factory-method="CreateStaticInstance"></bean>
2.例項工廠方法
需要先例項化工廠類,再通過工廠類物件呼叫例項方法獲取bean物件。
<bean id="xmlfactoryinstance" factory-bean="xmlfactory" factory-method="CreateInstance" destroy-method="DestoryMethod" init-method="InitMethod"></bean>
四、常見資料型別注入
(1)List屬性注入
使用<list>配置java.util.List型別的屬性。List屬性中元素可以是任何資料型別的值,如果是Java物件可以使用ref指定,或使用<bean>定義新例項。如果是基礎資料型別可直接用字串。<list>中的元素會按配置的先後順序排序。
<property name="lists">
<list>
<value>1</value>
<ref bean="CleanAir" />
<bean class="com.demo.model.CleanAir"/>
</list>
</property>
(2)Set屬性注入
使用<set>配置java.util.Set型別的屬性。Set屬性中元素可以是任何資料型別的值,如果是Java物件可以使用ref指定,或使用<bean>定義新例項。如果是基礎資料型別可直接用字串。<set>中的元素沒有先後順序。
<property name="sets"> <set> <value>1</value> <ref bean="CleanAir" /> <bean class="com.demo.model.CleanAir"/> </set> </property>
(3)Map屬性注入
使用<map>配置java.util.Map型別的屬性。<entry>配置Map裡的元素,Key指定索引,value指定值。如果是Java物件可以使用ref指定,或使用<bean>定義新例項。
<property name="maps"> <map> <entry key="key1" value="1"></entry> <entry key="key2" value-ref="CleanAir"></entry> <entry key="key3" > <bean class="com.demo.model.CleanAir"/> </entry> </map> </property>
(4)Properties屬性注入
使用<props>配置java.util.Properties型別的屬性。<props>配置一個Properties物件,<prop>配置一條屬性,屬性Key配置索引。
<property name="pros"> <props> <prop key="prokey1">prokeyA</prop> <prop key="prokey2">prokeyB</prop> </props> </property>
(5)自定義屬性編輯器
對於有一些屬性是沒法注入的,此時就需要自定義,比如日期型別。可以通過繼承PropertyEditorSupport的類,重寫setAsText方法來實現注入。這裡定義了CustomerProperty繼承PropertyEditorSupport,重寫了setAsText方法,並將該bean配置到xml中。
package com.demo.model; import java.beans.PropertyEditorSupport; import java.text.ParseException; import java.text.SimpleDateFormat; public class CustomerProperty extends PropertyEditorSupport { private String format="yyyy-MM-dd"; public String getFormat() { return format; } public void setFormat(String format) { this.format = format; } @Override public void setAsText(String text) throws IllegalArgumentException { SimpleDateFormat sdf=new SimpleDateFormat(format); //super.setAsText(text); try { //轉換物件,能過setValue方法重新賦值 this.setValue(sdf.parse(text)); } catch (ParseException e) { e.printStackTrace(); } } }
<bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer"> <property name="customEditors"> <map> <entry key="java.util.Date" value="com.demo.model.CustomerProperty"/> </map> </property> </bean>
配置之後就可以注入Date型別的屬性了。
<property name="date" value="2018-8-20"/>
這裡新建了XmlCollectionsDemo類,配置了上面的幾個型別的屬性來演示。
package com.demo.model; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class XmlCollectionsDemo { private List<Object> list; private Properties pros; private Set<Object> sets; private Map<String,Object> maps; private Date date; public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } public List<Object> list() { return list; } public void setLists(List<Object> list) { this.list = list; } public Properties getPros() { return pros; } public void setPros(Properties pros) { this.pros = pros; } public Set<Object> getSets() { return sets; } public void setSets(Set<Object> sets) { this.sets = sets; } public Map<String, Object> getMaps() { return maps; } public void setMaps(Map<String, Object> maps) { this.maps = maps; } public static void main( String[] args ) throws Exception { ApplicationContext context=new ClassPathXmlApplicationContext(new String[]{"ApplicationContext.xml"}); BeanFactory factory=context; XmlCollectionsDemo annontationInstance=(XmlCollectionsDemo)factory.getBean("xmlCollectionsDemo"); System.out.println(annontationInstance.list); System.out.println(annontationInstance.pros); System.out.println(annontationInstance.sets); System.out.println(annontationInstance.maps); System.out.println(annontationInstance.date); } }View Code
<bean id="xmlCollectionsDemo" class="com.demo.model.XmlCollectionsDemo"> <property name="lists"> <list> <value>1</value> <ref bean="CleanAir" /> <bean class="com.demo.model.CleanAir"/> </list> </property> <property name="sets"> <set> <value>1</value> <ref bean="CleanAir" /> <bean class="com.demo.model.CleanAir"/> </set> </property> <property name="maps"> <map> <entry key="key1" value="1"></entry> <entry key="key2" value-ref="CleanAir"></entry> <entry key="key3" > <bean class="com.demo.model.CleanAir"/> </entry> </map> </property> <property name="pros"> <props> <prop key="prokey1">prokeyA</prop> <prop key="prokey2">prokeyB</prop> </props> </property> <property name="date" value="2018-8-20"/> </bean>View Code
通過執行main方法,打印出屬性值。
[1, CleanAir, CleanAir]
{prokey2=prokeyB, prokey1=prokeyA}
[1, CleanAir, CleanAir]
{key1=1, key2=CleanAir, key3=CleanAir}
Mon Aug 20 00:00:00 CST 2018
五、初始化函式、銷燬函式
通過上面3種注入方式的學習也對通過xml對bean例項化有的瞭解,有的物件在例項化之後還需要執行某些初始化程式碼,但這些初始化程式碼還不能寫在建構函式中,此時可以將初始化程式碼寫到某個方法中,將init-method屬性值設定為該方法,Spring會強制執行該方法進行初始化。而又的物件在使用完畢之後需要釋放,可以使用destroy-method來進行銷燬。
public void DestoryMethod() { System.out.println("DestoryMethod"); } public void InitMethod() { System.out.println("InitMethod"); }
這裡先在XMLInstance類中增加了上面兩個方法來模擬銷燬和初始化方法。然後在xml配置bean時就可以設定destroy-method、init-method屬性的值對應兩個方法的方法名。註解中@PostConstruct對應init-method,@PreDestory對應destroy-method。
<bean id="xmlfactoryinstance" factory-bean="xmlfactory" factory-method="CreateInstance" destroy-method="DestoryMethod" init-method="InitMethod"></bean>
二、註解注入方式
一、常用註解介紹
學習完XML注入之後再學習註解方式注入就容易的多,註解方式注入主要涉及到@Autowired,@Resource,@Required,@Qualifier,@Value這幾個註解。在第2章節的2.2.4IOC例項中定義Person時就使用過@Autowired、@Qualifier。下面來了解下它們具體用法。
@Autowired:預設是按型別匹配注入bean,它可以對類成員變數、方法及建構函式進行標註,完成自動裝配的工作。在使用@Autowired時,首先在容器中查詢對應型別的bean,如果查詢結果剛好為一個,就將該bean裝配給@Autowired指定的資料,如果查詢的結果不止一個,那麼@Autowired會根據名稱來查詢。如果查詢的結果為空,那麼會丟擲異常。解決方法時,使用required=false。
@Required:適用於bean屬性setter方法,並表示受影響的bean屬性必須在XML配置檔案在配置時進行填充。否則,容器會丟擲一個BeanInitializationException異常。
@Qualifier:@Autowired預設是單例項的,但是在面向介面程式設計中,如果把一個屬性設定為介面型別,一個介面可能有多個實現,那到底是注入哪一個呢?為了解決這個問題,就有了@Qualifier。
@Value:在xml配置屬性時可以通過property的value設定預設值,@Value也可以為屬性設定預設值。
@Resource:預設按名稱匹配注入bean。要求提供一個bean名稱的屬性,如果屬性為空,則自動採用標註處的變數名或方法名作為bean的名稱。如果我們沒有在使用@Resource時指定bean的名字,同時Spring容器中又沒有該名字的bean,這時候@Resource就會退化為@Autowired即按照型別注入。
package com.demo.model; import javax.annotation.Resource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Required; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @Component public class AnnontationInstance { @Value("abc") private String name; public void setName(String name) { this.name = name; } //@Resource與@Autowired兩者選其一 // @Autowired // @Qualifier(value="cleanair") private IAir air; @Resource(name="CleanAir") public void setAir(IAir air) { this.air = air; } public void Breath() { System.out.println("Name:"+this.name+";Air:"+this.air.toString()); } }
上面程式碼使用@Value註解為name設定了預設值,使用@Resources設定bean的名稱為IAir屬性注入bean,也可以使用@[email protected]為IAir注入bean。
二、開啟註解
上面配置完註解之後,還要告訴Spring開啟註解,這樣@Autowired、@Resources這些註解才起作用。開啟有兩種比較簡單的方式。
1.在xml配置檔案中使用context:annotation-config
<context:annotation-config />
2.在xml配置檔案中使用context:component-scan
<context:component-scan base-package="com.demo.model"/>
相關推薦
SSM框架專案搭建系列(五)—Spring之Bean的註解注入
applicationContext.xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/bea
Spring之Bean的注入
Bean的配置中介紹的是Bean宣告問題,在哪宣告怎麼宣告的問題。Bean的注入是怎麼例項化,怎麼注入的問題。Bean注入的方式有兩種,一種是在XML中配置,另一種則是使用註解的方式注入。 一、XML方式注入 XML方式注入一般有三種方式:屬性注入、建構函式注入和工廠方法注入。 一、屬性注入在傳統的物件例項化
SSM框架專案搭建系列(四)— Spring之bean的XML注入方式
在XML中可使用兩種方式進行注入:建構函式注入和setter注入 建構函式注入constructor 直接傳值 applicationContext.xml <bean id="helloworldBeanId" class="com.ssm.b
Spring 之Bean的裝配
med post java set pac () 構造參數 單元 引用 Spring Bean的裝配分為3中: 1、隱式發現和自動裝配 @Component:將一個Java類聲明為Bean(組件類),等待Spring掃描發現。 @ComponentScan:啟用組件
Spring之Bean的註入
函數的參數 span sta 工廠類 false 介紹 類型 簡單 prope Bean的配置中介紹的是Bean聲明問題,在哪聲明怎麽聲明的問題。Bean的註入是怎麽實例化,怎麽註入的問題。Bean註入的方式有兩種,一種是在XML中配置,另一種則是使用註解的方式註入。 一、
Spring之Bean的作用域與生命周期
src efi lin 控制 初始化 troy [] 分享 isp 在前面博客中提到容器啟動獲得BeanDefinition對象中有一個scope 屬性。該屬性控制著bean對象的作用域。本章節介紹Bean的作用域及生命周期,了解bean是怎麽來的又怎麽沒的。 一、Bean
Spring 之 Bean 的 Scope
Bean 的 Scope Scope 描述的是 Spring 容器如何新建 Bean 的例項的. Spring 的 Scope 有以下幾種,通過 @Scope 註解來實現. Singleton: 一個 Spring 容器中只有一個 Bena 的例項,此為 Spring
Spring之Bean的生命周期
web nec connector start jasper dep oca cep table ---恢復內容開始--- Spring中關於Bean的生命周期,我總結的大致過程如下: 1、用戶調用BeanFactory接口的getBean()方法請求一個
Spring之Bean學習
簡述:Spring框架主要是涉及到IOC(控制反轉)和AOP(切面程式設計)兩大重點 IOC和DI(依賴注入)其實就是等同的意思,就是建立物件和維護物件,放在一個容器裡,直接依賴注入即可使用 AOP的存在目的是為了解耦即高內聚,低耦合 Bean的取值範圍 &nb
Spring之bean例項的建立
在上一篇部落格中,我們已經對bean的載入跟著原始碼完整的走了一遍,程式碼讀起來很輕鬆,主要還是Spring的程式設計風格,它把每段程式碼分割成一個一個的小邏輯,使得每個邏輯處理起來都不是很負責,非常有利於我們學習。接下來,我們繼續對bean例項的建立進行閱讀。
也談Spring之依賴注入DI/控制反轉IOC
首先提問, 什麼是 Spring IOC 容器? Spring 框架的核心是 Spring 容器。容器建立物件,將它們裝配在一起,配置它們並管理它們的完整生命週期。Spring 容器使用依賴注入來管理組成應用程式的元件。容器通過讀取提供的配置元資料來接收物件
spring的Bean注入和P標籤使用
1.構造方法引數 對應 配置檔案 <constructor-arg> 元素 可以index|name|type 三選一 、三選二 ; ref|value 二選一 2. setter方法注入(開發推薦) 為需要注入屬性提供setter方法 配置 每個注入
Spring之Bean管理------註解方式
編寫測試類 1,編寫相關的類 public interface UserDao { public void sayHello(); } public class UserDaoImpl implements UserDao { @Override public void sayHello() { S
Spring之Bean實現了ApplicationContextAware等aware介面,對於setApplicationContext方法執行時間點的說明
在Spring中,如果Bean物件實現了ApplicationContextAware介面,則Spring在完成Bean的初始化後,會將ApplicationContext上下文物件注入至該Bean物件中,注入方法為呼叫Bean的setApplicationContex
spring之bean的Scope
上篇文章較為詳細了對各種情況下bean依賴的配置做了說明,但一直沒有對Scope這個屬性進行說明。本篇將一起學習。本文演示程式碼下載地址 當我們在xml配置檔案中配置一個bean的定義的時候,可以認為是配置了一個模板,可以根據這個模板來生成很多個物件來滿足整個應用程式的依賴
Spring中bean注入初始化方式—通過註解@Configuration @bean
雖然 2.0 版本釋出以來,Spring 陸續提供了十多個註解,但是提供的這些註解只是為了在某些情況下簡化 XML 的配置,並非要取代 XML 配置方式。這一點可以從 Spring IoC 容器的初始化類可以看出:ApplicationContext 介面的最常用的實現類是
Java多執行緒中Spring的Bean注入失敗
問題說明 : 在spring框架進行專案開發,平時遇到了需要批量處理的資料的時候,會選擇多執行緒進行資料批跑,但是會發現,啟動多執行緒後,執行緒會出現service或者mapper檔案注入失敗的問題,導致執行緒啟動失敗,其中bean的注入方式選擇的是spring常規的註解@A
spring之依賴注入與控制反轉的區別
IoC——Inversion of Control 控制反轉 DI——Dependency Injection 依賴注入 要想理解上面兩個概念,就必須搞清楚如下的問題: 參與者都有誰?依賴:誰依賴於誰?為什麼需要依賴? 注入:誰注入於誰?到底
Spring之Bean的作用域與生命週期
在前面部落格中提到容器啟動獲得BeanDefinition物件中有一個scope 屬性。該屬性控制著bean物件的作用域。本章節介紹Bean的作用域及生命週期,瞭解bean是怎麼來的又怎麼沒的。 一、Bean的作用域在Bean容器啟動會讀取bean的xml配置檔案,然後將xml中每個bean元素分別轉換成Be
Spring之Bean的配置方式
在部落格中為了演示容器Bean例項化時暴露出的幾個介面,將UserBean配置在XML中,其實常見的Bean的配置有3種。1.基於xml配置Bean 2.使用註解定義Bean 3.基於java類提供Bean定義資訊。 一、基於xml配置Bean 基於XML配置Bean時,Spring通過<bean>