Spring 系列(一) IOC應用

1. Spring IOC基礎

Spring框架IOC實現(xiàn) JavaSE應用下該IOC容器啟動方式 JavaWeb應用下該IOC容器啟動方式
純xml new ClassPathXmlApplicationContext("beans.xml");
或者new FileSystemXmlApplicationContext("c:/beans.xml");
ContextLoaderListener(監(jiān)聽器去加載xml)
xml+注解 new ClassPathXmlApplicationContext("beans.xml");
或者new FileSystemXmlApplicationContext("c:/beans.xml");
ContextLoaderListener(監(jiān)聽器去加載xml)
純注解模式 new AnnotationConfigApplicationContext("SpringConfig.class"); ContextLoaderListener(監(jiān)聽器去加載注解配置類)

1.1 BeanFactory與ApplicationContext區(qū)別

?BeanFactory是Spring框架中IoC容器的頂層接?,它只是?來定義?些基礎功能,定義?些基礎規(guī)范,?ApplicationContext是它的?個?接?,所以ApplicationContext是具備BeanFactory提供的全部功能的漩蟆。
?通常垒探,我們稱BeanFactory為SpringIOC的基礎容器,ApplicationContext是容器的?級接?怠李,?BeanFactory要擁有更多的功能圾叼,?如說國際化?持和資源訪問(xml,java配置類)等等



啟動容器的方式

  • Java環(huán)境下啟動IOC容器
    1. ClassPathXmlApplicationContext:從類的根路徑下加載配置文件(推薦使用)
    2. FileSystemXmlApplicationContext:從磁盤路徑下加載配置文件
    3. AnnotationConfigApplicationContext:純注解模式下啟動Spring容器
  • Web環(huán)境下啟動IOC容器
    1. 從xml啟動容器
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
 <display-name>Archetype Created Web Application</display-name>
 <!--配置Spring ioc容器的配置?件-->
 <context-param>
 <param-name>contextConfigLocation</param-name>
 <param-value>classpath:applicationContext.xml</param-value>
 </context-param>
 <!--使?監(jiān)聽器啟動Spring的IOC容器-->
 <listener>
 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>
</web-app>

?2. 從配置類加載啟動容器

<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
 <display-name>Archetype Created Web Application</display-name>
 <!--告訴ContextloaderListener知道我們使?注解的?式啟動ioc容器-->
 <context-param>
 <param-name>contextClass</param-name>
 <param-value>org.springframework.web.context.support.AnnotationConfigWebAppli
cationContext</param-value>
 </context-param>
 <!--配置啟動類的全限定類名-->
 <context-param>
 <param-name>contextConfigLocation</param-name>
 <param-value>com.lagou.edu.SpringConfig</param-value>
 </context-param>
 <!--使?監(jiān)聽器啟動Spring的IOC容器-->
 <listener>
 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>
</web-app>

1.2 純xml形式

  • 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"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
 https://www.springframework.org/schema/beans/spring-beans.xsd">
  • 實例化bean的三種方式

方式一:使用無參構造函數(shù)
?在默認情況下捺癞,它會通過反射調用無參構造函數(shù)來創(chuàng)建對象夷蚊。如果 類中沒有無參構造函數(shù),將創(chuàng)建失敗髓介。

<!--配置service對象-->
<bean id="userService" class="com.lagou.service.impl.TransferServiceImpl">
</bean>

方式二:使用靜態(tài)方法創(chuàng)建
?在實際開發(fā)中惕鼓,我們使?的對象有些時候并不是直接通過構造函數(shù)就可以創(chuàng)建出來的,它可能在創(chuàng)建的過程 中會做很多額外的操作唐础。此時會提供?個創(chuàng)建對象的?法箱歧,恰好這個?法是static修飾的?法,即是此種情況一膨。
?例如呀邢,我們在做Jdbc操作時,會?到java.sql.Connection接?的實現(xiàn)類豹绪,如果是mysql數(shù)據(jù)庫价淌,那么?的就是JDBC4Connection,但是我們不會去寫 JDBC4Connection connection = new JDBC4Connection() 瞒津,因為我們要注冊驅動蝉衣,還要提供URL和憑證信息,? DriverManager.getConnection ?法來獲取連接巷蚪。
?那么在實際開發(fā)中买乃,尤其早期的項?沒有使?Spring框架來管理對象的創(chuàng)建,但是在設計時使?了??模式解耦钓辆,那么當接?spring之后,??類創(chuàng)建對象就具有和上述例?相同特征,即可采?此種?式配置前联。

<!--使?靜態(tài)?法創(chuàng)建對象的配置?式-->
<bean id="userService" class="com.lagou.factory.BeanFactory"
 factory-method="getTransferService"></bean>

方式三:使用實例化方法創(chuàng)建
?此種方式和上?靜態(tài)方法創(chuàng)建其實類似功戚,區(qū)別是用于獲取對象的方法不再是static修飾的了,而是類中的?個普通方法似嗤,且需要配置工廠bean啸臀,并在業(yè)務bean中配置factory-bean,factory-method屬性。
?在早期開發(fā)的項?中烁落,工廠類中的方法有可能是靜態(tài)的乘粒,也有可能是非靜態(tài)方法,當是非靜態(tài)方法時伤塌,即可采用下?的配置方式:

<!--使?實例?法創(chuàng)建對象的配置?式-->
<bean id="beanFactory" class="com.lagou.factory.instancemethod.BeanFactory"></bean>
<bean id="transferService" factory-bean="beanFactory" factory-method="getTransferService"></bean>
  • Bean的X以及生命周期

?在spring框架管理Bean對象的創(chuàng)建時灯萍,Bean對象默認都是單例的,但是它?持配置的?式改變作?范圍每聪。作?范圍如下旦棉。

Scope Description
singleton 單例模式,使用 singleton 定義的 Bean 在 Spring 容器中只有一個實例药薯,這也是 Bean 默認的作用域绑洛。
prototype 原型模式,每次通過 Spring 容器獲取 prototype 定義的 Bean 時童本,容器都將創(chuàng)建一個新的 Bean 實例真屯。
request 在一次 HTTP 請求中,容器會返回該 Bean 的同一個實例穷娱。而對不同的 HTTP 請求绑蔫,會返回不同的實例,該作用域僅在當前 HTTP Request 內有效鄙煤。晾匠。
seesion 在一次 HTTP Session 中,容器會返回該 Bean 的同一個實例梯刚。而對不同的 HTTP 請求凉馆,會返回不同的實例,該作用域僅在當前 HTTP Session 內有效亡资。
application ServletContext的生命周期澜共。僅在可感知web的Spring應用程序上下文中有效。
websocket websocket的生命周期锥腻。僅在可感知web的Spring應用程序上下文中有效

在上圖中提供的這些選項中嗦董,我們實際開發(fā)中?到最多的作?范圍就是singleton(單例模式)和prototype(原型模式,也叫多例模式)瘦黑。配置?式參考下?的代碼:

<!--配置service對象-->
<bean id="transferService"
class="com.lagou.service.impl.TransferServiceImpl" scope="singleton">
</bean>
  • 不同作用范圍的生命周期
  1. 單例模式
    對象出生:當創(chuàng)建容器時京革,對象就被創(chuàng)建
    對象存活:只要容器在庸毫,對象一直活著
    對象死亡:當銷毀容器時,對象就被銷毀了
    一句話總結: 單例的bean對象生命周期和容器相同
  2. 多例模式
    對象出生:當使用對象時勋篓,創(chuàng)建新的對象實例
    對象存活:只要對象在使用中狮暑,對象一直活著
    對象死亡:當對象長時間不用時,被java的垃圾回收哦器回收了
    一句話總結: 多例模式的bean對象廊勃,Spring框架只負責創(chuàng)建不負責銷毀懈贺。
  • Bean標簽屬性
    ?在基于xml的IOC配置中,bean標簽是最基礎的標簽坡垫。它表示了IOC容器中的一個對象梭灿。換句話說,如果一個對象想讓Spring管理冰悠,在xml的配置中都需要使用此標簽配置堡妒,Bean標簽的屬性如下:
    • id屬性:用于給bean提供一個唯一標識。在一個標簽內部屿脐,標識必須唯一涕蚤。
    • class屬性:用于指定創(chuàng)建Bean對象的全限定類名。
    • name屬性:用于給bean 提供一個或多個名稱的诵,多個名稱用空格分隔万栅。
    • factory-bean屬性:用于指定創(chuàng)建當前bean對象的工廠bean的唯一標識。當指定了此屬性之后西疤,class屬性失效烦粒。
    • factory-method屬性:用于指定創(chuàng)建當前bean對象的工廠方法,如配合factory-bean使用代赁,則class屬性失效(實例化方法創(chuàng)建)扰她;如配合class屬性使用,則方法必須是static的(靜態(tài)方法創(chuàng)建)芭碍。
    • scope屬性:用于指定bean對象的作用范圍徒役。通常情況下就是singleton,當需要用到多例模式時窖壕,可以配置為prototype忧勿。
    • init-method屬性:用于指定bean對象的初始化方法,此方法會在bean對象裝配后調用瞻讽。必須是無參方法鸳吸。
    • destory-method屬性:用于指定bean對象的銷毀方法,此方法會在bean對象銷毀前執(zhí)行速勇。他只能為scope是singleton時起作用晌砾。
  • DI依賴注入的xml配置
    • 依賴注入分類
      • 按照注入的方式分類
        構造函數(shù)注入:顧名思義,就是利用帶參構造函數(shù)實現(xiàn)對類成員的數(shù)據(jù)賦值烦磁。
        set方法注入:它是通過類成員的set方法實現(xiàn)數(shù)據(jù)的注入养匈。
      • 按照注入的數(shù)據(jù)類型分類
        基本類型和String:注入的數(shù)據(jù)類型是基本類型或者是字符串類型的數(shù)據(jù)哼勇。
        其他Bean類型:注入的數(shù)據(jù)類型是對象類型,稱為其他的Bean的原因是呕乎,這個對象要求出現(xiàn)在IOC容器中的猴蹂,那么針對當前Bean來說,就是其他Bean了楣嘁。
        復雜類型(集合類型):注入的數(shù)據(jù)類型是Array,List珍逸,Set逐虚,Map,Properties中的一種類型谆膳。
    • 依賴注入的配置實現(xiàn)之構造函數(shù)注入
      顧名思義叭爱,就是利用構造函數(shù)實現(xiàn)對類成員的賦值。它的使用要求是漱病,類中提供的構造函數(shù)參數(shù)個數(shù)必須是配置的參數(shù)個數(shù)一致买雾,且數(shù)據(jù)類型匹配。同時需要注意的是杨帽,當沒有無參構造時漓穿,則必須提供構造函數(shù)參數(shù)的注入,否則Spring框架會報錯注盈。

      在使用構造函數(shù)注入時晃危,涉及到的標簽是constructor-arg,該標簽有如下屬性:
      name:用于給構造函數(shù)中指定名稱的參數(shù)賦值老客。
      index:用于給構造函數(shù)指定索引位置的參數(shù)賦值僚饭。
      value:用于指定基本類型或者String類型的數(shù)據(jù)。
      ref:用于指定其他Bean類型的數(shù)據(jù)胧砰。寫的是其他bean的唯一標識鳍鸵。
    • 依賴注入的配置實現(xiàn)之set方法注入
      顧名思義,就是利用字段的set方法實現(xiàn)賦值的注入方式尉间。

      在使用set方法注入時偿乖,需要使用的標簽是property,該標簽有如下屬性:
      name:指定注入時調用的set方法名稱乌妒。(注:不包含set這三個字母)
      value:指定注入的數(shù)據(jù)汹想,它支持基本類型和String類型。
      ref:指定注入的數(shù)據(jù)撤蚊,它指定其他bean類型古掏。寫的是其他的bean的唯一標識。
    • 復雜數(shù)據(jù)類型注入
      ?首先說明一下復雜屬性類型侦啸,它指的是集合類型數(shù)據(jù)槽唾。集合分兩類某一類是List結構(數(shù)組結構)丧枪,一類是Map接口(鍵值對)。
      ?接下來就是注入的方式的選擇庞萍,只能在構造函數(shù)和set方法中選擇拧烦,我們的示例選擇set方法注入。




      ?在List結構的集合數(shù)據(jù)注?時钝计, array , list , set 這三個標簽通?恋博,另外注值的 value 標簽內部可以直接寫值,也可以使? bean 標簽配置?個對象私恬,或者? ref 標簽引??個已經配合的bean的唯?標識债沮。
      ?在Map結構的集合數(shù)據(jù)注?時,map 標簽使? entry ?標簽實現(xiàn)數(shù)據(jù)注?本鸣,entry 標簽可以使?key和value屬性指定存?map中的數(shù)據(jù)疫衩。使?value-ref屬性指定已經配置好的bean的引?。同時 entry 標簽中也可以使? ref 標簽荣德,但是不能使? bean 標簽闷煤。? property 標簽中不能使? ref 或者 bean 標簽引?對象。

1.3 xml與注解相結合模式

注意:

  1. 實際企業(yè)開發(fā)中涮瞻,純xml模式使?已經很少了
  2. 引?注解功能鲤拿,不需要引?額外的jar
  3. xml+注解結合模式,xml?件依然存在饲宛,所以皆愉,spring IOC容器的啟動仍然從加載xml開始
  4. 哪些bean的定義寫在xml中,哪些bean的定義使?注解
    第三?jar中的bean定義在xml艇抠,?如德魯伊數(shù)據(jù)庫連接池??開發(fā)的bean定義使?注解
  • xml中標簽與注解的對應(IOC)
xml形式 對應的注解形式
標簽 @Component("accountDao")幕庐,
注解加在類上,bean的id屬性內容直接配置在注解后面家淤,默認定義這個bean的id是類的類名首字母小寫异剥;
另外,針對分層代碼開發(fā)提供了@Component的三種別名絮重,@Controoler冤寿、@Service、@Repository分別控制層類青伤、服務層類督怜、dao層類的bean定義,這四個注解的用法完全一樣狠角,只是為了更清晰的區(qū)別
標簽的scope屬性 @Scope("prototype")号杠,默認單例,注解加在類上
標簽的init-method屬性 @PostConstruct,注解加在方法上姨蟋,該方法就是初始化后調用的方法
標簽的destory-method屬性 @PreDestory屉凯,注解加在方法上,該方法就是銷毀前調用的方法
  • DI依賴注入的注解實現(xiàn)方式
  1. @Autowire(推薦使用)

@Autowired為Spring提供的注解眼溶,需要導?包org.springframework.beans.factory.annotation.Autowired悠砚。
@Autowire采用的策略為按照類型注入。

public class TransferServiceImpl {
 @Autowired
 private AccountDao accountDao;
}

?如上代碼所示堂飞,這樣裝配回去spring容器中找到類型為AccountDao的類灌旧,然后將其注?進來。這樣會產??個問題绰筛,當?個類型有多個bean值的時候节榜,會造成?法選擇具體注?哪?個的情況,
?這個時候我們需要配合著@Qualifier使?别智。
?@Qualifier告訴Spring具體去裝配那個對象。

public class TransferServiceImpl {
@Autowired
@Qualifier(name="jdbcAccountDaoImpl") 
private AccountDao accountDao;
}

這個時候我們就可以通過類型和名稱定位到我們想注入的對象稼稿。

  1. @Resouce

@Resource 注解由 J2EE 提供薄榛,需要導?包 javax.annotation.Resource。
@Resource 默認按照 ByName ?動注?让歼。

public class TransferService {
 @Resource 
 private AccountDao accountDao;
 @Resource(name="studentDao") 
 private StudentDao studentDao;
 @Resource(type="TeacherDao") 
 private TeacherDao teacherDao;
 @Resource(name="manDao",type="ManDao") 
 private ManDao manDao;
} 
  • 如果同時指定了name和type敞恋,則從Spring上下文中找到唯一匹配的bean進行裝配。
  • 如果指定了name谋右,則從上下文中查找名稱(id)匹配的bean進行裝配硬猫,找不到則拋異常。
  • 如果指定了type改执,則從上下文中查找類似匹配的唯一bean進行裝配啸蜜,找不到或找到多個則拋異常。
  • 如果既沒有指定name也沒有指定type辈挂,則自動按照byName方式進行裝配衬横。

1.4 純注解模式

改造xm+注解模式,將xml中遺留的內容全部以注解的形式遷移出去终蒂,最終刪除xml蜂林,從Java配置類啟動拇泣。
對應注解
@Configuration注解,表示當前類是一個配置類
@ComponentScan注解霉翔,代替context:componentr-scan
@PropertySource,引入其他配置類
@Import早龟,引入其他配置類
@Value對變量賦值猫缭,可以直接賦值,也可以使用${}讀取資源配置文件中的信息
@Bean將方法返回對象加入Spring IOC容器

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末猜丹,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子射窒,更是在濱河造成了極大的恐慌,老刑警劉巖脉顿,帶你破解...
    沈念sama閱讀 217,907評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異艾疟,居然都是意外死亡,警方通過查閱死者的電腦和手機敢辩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評論 3 395
  • 文/潘曉璐 我一進店門蔽莱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人戚长,你說我怎么就攤上這事盗冷。” “怎么了同廉?”我有些...
    開封第一講書人閱讀 164,298評論 0 354
  • 文/不壞的土叔 我叫張陵仪糖,是天一觀的道長。 經常有香客問我迫肖,道長锅劝,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,586評論 1 293
  • 正文 為了忘掉前任蟆湖,我火速辦了婚禮鸠天,結果婚禮上,老公的妹妹穿的比我還像新娘帐姻。我一直安慰自己稠集,他們只是感情好,可當我...
    茶點故事閱讀 67,633評論 6 392
  • 文/花漫 我一把揭開白布饥瓷。 她就那樣靜靜地躺著剥纷,像睡著了一般。 火紅的嫁衣襯著肌膚如雪呢铆。 梳的紋絲不亂的頭發(fā)上晦鞋,一...
    開封第一講書人閱讀 51,488評論 1 302
  • 那天,我揣著相機與錄音,去河邊找鬼悠垛。 笑死线定,一個胖子當著我的面吹牛,可吹牛的內容都是我干的确买。 我是一名探鬼主播斤讥,決...
    沈念sama閱讀 40,275評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼湾趾!你這毒婦竟也來了芭商?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,176評論 0 276
  • 序言:老撾萬榮一對情侶失蹤搀缠,失蹤者是張志新(化名)和其女友劉穎铛楣,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體艺普,經...
    沈念sama閱讀 45,619評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡簸州,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,819評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了勿侯。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片缴罗。...
    茶點故事閱讀 39,932評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡面氓,死狀恐怖舌界,靈堂內的尸體忽然破棺而出泰演,到底是詐尸還是另有隱情,我是刑警寧澤藐握,帶...
    沈念sama閱讀 35,655評論 5 346
  • 正文 年R本政府宣布猾普,位于F島的核電站本谜,受9級特大地震影響,放射性物質發(fā)生泄漏溜在。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,265評論 3 329
  • 文/蒙蒙 一仆葡、第九天 我趴在偏房一處隱蔽的房頂上張望培遵。 院中可真熱鬧,春花似錦嗡呼、人聲如沸皇耗。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽呜袁。三九已至,卻和暖如春虹钮,著一層夾襖步出監(jiān)牢的瞬間膘融,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評論 1 269
  • 我被黑心中介騙來泰國打工春畔, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留岛都,地道東北人。 一個月前我還...
    沈念sama閱讀 48,095評論 3 370
  • 正文 我出身青樓线召,卻偏偏與公主長得像多矮,于是被迫代替她去往敵國和親哈打。 傳聞我的和親對象是個殘疾皇子料仗,可洞房花燭夜當晚...
    茶點故事閱讀 44,884評論 2 354

推薦閱讀更多精彩內容