本文將詳細(xì)介紹Spring Bean配置的三種不同方式的特點(diǎn)與使用條件。
主要包括:
基于XML的配置方式
基于注解的配置方式
基于Java類的配置方式
一.基于XML的配置
我們應(yīng)該怎么理解和認(rèn)識(shí)Spring的配置文件呢诲侮?
? ? ? ? 其實(shí)镀虐,Spring的配置文件是Spring容器對(duì)Bean進(jìn)行生產(chǎn)以及關(guān)系注入的圖紙,他是Spring的基礎(chǔ)沟绪。如果我們沒有配置文件的話刮便,則Spring的容器將無從談起。
? ? ? ? Spring 的配置文件是用于指導(dǎo) Spring 工廠進(jìn)行 Bean 的生產(chǎn)绽慈、依賴關(guān)系注入及 Bean 實(shí)例分發(fā)的“圖紙”恨旱, J2EE 程序員必須學(xué)會(huì)并靈活應(yīng)用這份“圖紙”,準(zhǔn)確地表達(dá)自己的“生產(chǎn)意圖”坝疼。它是一個(gè)或多個(gè)標(biāo)準(zhǔn)的XML文檔搜贤,其ApplicationContext.xml是Spring的默認(rèn)配置文件,當(dāng)容器啟動(dòng)時(shí)找不到其他的配置文件時(shí)钝凶,則會(huì)嘗試加載這個(gè)默認(rèn)的配置文件仪芒。
Spring容器成功啟動(dòng)需要以下三方面的條件同時(shí)具備:
Spring的類包必須已經(jīng)放在Spring的類容器下面
應(yīng)用程序應(yīng)當(dāng)為Spring提供完備的Bean的配置信息
Bean的類都已經(jīng)放在Spring的類容器下面? ??
Spring啟動(dòng)時(shí)讀取應(yīng)用程序提供的Bean的配置信息,并在Spring容器中生成一份相應(yīng)的Bean的配置注冊(cè)表耕陷,然后根據(jù)這張注冊(cè)表來實(shí)例化Bean掂名,裝配好Bean之間的依賴關(guān)系,為上層應(yīng)用提供準(zhǔn)備就緒的運(yùn)行環(huán)境哟沫。
而bean的配置信息就是Bean的元數(shù)據(jù)信息饺蔑,他由以下五個(gè)方面來組成:
Bean的實(shí)現(xiàn)類
Bean的屬性信息 比如:數(shù)據(jù)源的連接數(shù),用戶名和密碼等等嗜诀。
Bean的依賴關(guān)系 Spring根據(jù)依賴關(guān)系配置完成Bean之間的裝配
Bean的行為配置 比如:生命周期范圍以及生命周期各個(gè)過程的回調(diào)函數(shù)等
Bean的創(chuàng)建方式定義 主要說明是通過構(gòu)造器還是工廠方法來構(gòu)造Bean
接下來是他們之間的相互關(guān)系:
有時(shí)猾警,一個(gè)項(xiàng)目中可能存在多個(gè)配置文件,那么Spring項(xiàng)目加載多個(gè)配置文件的方法:
在配置文件中使用import來導(dǎo)入所需的配置文件裹虫。
將多個(gè)配置文件構(gòu)造為一個(gè)數(shù)組肿嘲,然后傳遞給ApplicationContext實(shí)現(xiàn)加載多個(gè)配置文件。
這兩種方式都是通過調(diào)用BeanDefinitionReader來讀取定義文件的筑公,在內(nèi)部實(shí)現(xiàn)上沒有任何的區(qū)別雳窟。
? ? ??在大型的Spring項(xiàng)目當(dāng)中,所有的bean配置在一個(gè)配置文件當(dāng)中很不容易管理且也不利于團(tuán)隊(duì)的開發(fā)。通常在開發(fā)過程當(dāng)中封救,我們會(huì)按照功能模塊和開發(fā)人員來將配置文件分成多個(gè)拇涤。這樣會(huì)有利與模塊的劃分。接下來我們需要使用import屬性來引入多個(gè)配置文件到項(xiàng)目當(dāng)中誉结。
假如我們的項(xiàng)目需要用到多個(gè)配置文件鹅士,且配置文件位于不同的文件夾下,比如:
Spring-Common.xml位于common文件夾下
Spring-Connection.xml位于connection文件夾下
Spring-Module.xml位于module文件夾下
傳統(tǒng)加載方式:
但是這種方法不宜組織惩坑,且不宜維護(hù)掉盅。
則我們使用整合配置文件:Spring-All-Module.xml
在文件當(dāng)中使用import直接將其他的配置文件導(dǎo)入到這個(gè)文件當(dāng)中就好了。
整合后加載方式:
ApplicationContext?context?=?new?ClassPathXmlApplicationContext(“Spring-All-Module.xml”);??
可以看到配置文件是整個(gè)Spring項(xiàng)目的靈魂以舒,我們先來看一下Spring配置文件的一般結(jié)構(gòu):
可以看到一個(gè)簡(jiǎn)單的Spring配置文件就是這樣趾痘。
其中:
Import標(biāo)簽可以放在Beans標(biāo)簽下的任何位置,沒有順序關(guān)系蔓钟。
bean3和bean2是同一個(gè)Bean永票,bean3是bean2的別名。
? ? ? ? Spring 的配置文件是基于XML格式的滥沫,Spring1.0的配置文件采用DTD格式侣集,Spring2.0以后使用Schema的格式,后者讓不同類型的配置擁有了自己的命名空間兰绣,使配置文件更具有擴(kuò)展性世分。
采取基于Schema的配置格式,文件頭的聲明會(huì)復(fù)雜一些狭魂,請(qǐng)看一個(gè)簡(jiǎn)單示例:
我們?cè)谏厦娴拇a中定義了三個(gè)命名空間罚攀,
首先我們定義了一個(gè)默認(rèn)命名空間,他沒有空間名雌澄,用于Spring Bean的定義。
接下來我們命名了一個(gè)xsi命名空間杯瞻,這個(gè)命名空間用于為每個(gè)文檔中命名空間指定相對(duì)應(yīng)的schema的樣式文件镐牺。是標(biāo)準(zhǔn)組織定義的標(biāo)準(zhǔn)命名空間。
我們還命名了一個(gè)aop的命名空間魁莉,這個(gè)命名空間是Spring配置aop的命名空間睬涧,是用戶自定義的命名空間。
命名空間的定義分為了兩個(gè)步驟:
指定命名空間的名稱旗唁,需要指定命名空間的縮類名和全名
指定命名空間的schema文檔樣式文件的位置畦浓,用空格或回車行來進(jìn)行分割。
指定命名空間schema地址有兩個(gè)用途:
xml解析器可以獲取schema文件检疫,并對(duì)文檔進(jìn)行格式合法性驗(yàn)證
在開發(fā)環(huán)境下讶请,IDE可以用schema文件來對(duì)文檔編輯器進(jìn)行誘導(dǎo)功能。
Spring3.0 的配置Schema文件分布在各模塊類包中屎媳,如果模塊擁有對(duì)應(yīng)的Schema文件夺溢,則可以在模塊類包中找到一個(gè)config目錄论巍,Schema文件就位于該目錄中,如下是對(duì)這些Schema文件的用途進(jìn)行了簡(jiǎn)單說明:
示例說明:Spring-beans-3.0.xsd
命名空間:http://www.springframework.org/schema/beans
Schema 文件:http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
可以看出在Spring3.0當(dāng)中风响,所有的Schema文件的命名空間以及對(duì)應(yīng)的位置都和Beans這個(gè)Schema文件是類似的嘉汰。
那么接下來來了解以下Spring當(dāng)中其他Schema文件的用途:
spring-beans-3.0.xsd:Spring3.0最主要的配置文件,主要是用于配置Bean
spring-aop-3.0.xsd:aop配置定義的schema
spring-tx-3.0.xsd:聲明式事物配置定義的Schema
spring-mvc-3.0.xsd:Spring3.0當(dāng)中新增的
spring-util-3.0.xsd:是為簡(jiǎn)化某些復(fù)雜的標(biāo)準(zhǔn)配置而提供的Schema
spring-jee-3.0.xsd:是為簡(jiǎn)化J2EE中EJB等功能的配置而提供的Schema
spring-jdbc-3.0.xsd:為Spring內(nèi)接數(shù)據(jù)庫(kù)而提供的Schema状勤,3.0新增
spring-jms-3.0.xsd:jms配置的Schema
spring-lang-3.0.xsd:增加了對(duì)動(dòng)態(tài)語(yǔ)言的支持鞋怀,為集成動(dòng)態(tài)語(yǔ)言而定義
spring-oxm-3.0.xsd:配置對(duì)象xml映射到schema,3.0新增
spring-task-3.0.xsd:任務(wù)調(diào)度的Schema
spring-tool-3.0.xsd:為集成Schema一些有用工具而提供的Schema
二.基于注解的配置
Spring2.0開始引入基于注解的配置方式,即Bean的定義信息可以通過在Bean的實(shí)現(xiàn)類上標(biāo)注注解實(shí)現(xiàn)持搜。
具體關(guān)于注解的知識(shí)請(qǐng)看Java注解(Annotation)介紹
@Component是Spring容器中的基本注解密似,表示容器中的一個(gè)組件(bean),可以作用在任何層次朵诫,下面的示例介紹該注解的使用方法辛友。
注解配置示例:
此外,還有一些其他的可以被用來注解bean的注解剪返,這些可以讓注解類本身的用途更加清晰废累,此外,特定的注解也具備特定的功能脱盲。
Spring在2.5后提供了一個(gè)context的命名空間邑滨,它提供了通過掃描類包來加載利用注解定義的Bean的方式。
在context中可以使用resource-pattern來過濾出特定的類钱反。
默認(rèn)情況下加載的是package下的*.class即掃描全部類掖看,在使用了resource-pattern之后,則只掃描package下的anno子包下的所有類面哥。
不過使用resource-pattern并不能提供給我們完善的功能哎壳,所有我們得使用過濾子元素的方法。
其中:
include-filter表示要包含的目標(biāo)類尚卫,
exclude-filter表示要排除在外的目標(biāo)類
Spring3.0提供了一系列的針對(duì)依賴注入的注解归榕,這使得Spring IoC在XML文件之外多了一種可行的選擇,主要包含如下注解類型:
Bean的定義注解
Bean的生命周期注解
Bean的依賴檢查注解
Bean的自動(dòng)裝配注解
1.Bean的定義注解
Spring自2.0開始吱涉,陸續(xù)引入了一些注解用于簡(jiǎn)化Spring的開發(fā)刹泄。
@Repository注解便屬于最先引入的一批,用于將數(shù)據(jù)訪問層(DAO層)的類標(biāo)識(shí)為Spring Bean怎爵。具體使用如下:
①首先使用@Repository將DAO類聲明為Bean
如此的話特石,我們便不在需要在XML當(dāng)中顯式使用bean來進(jìn)行bean的配置。Spring容器在初始化的時(shí)候便會(huì)自動(dòng)掃描base-package所指定的包以及子包下面的所有class文件鳖链。所有標(biāo)注為Repository的類將被自動(dòng)注冊(cè)為bean姆蘸。
為什么Repository只能標(biāo)注在DAO類上面呢?
? ? ? ?因?yàn)樵撟⒔獾淖饔貌恢皇菍㈩愖R(shí)別為bean,同時(shí)他還能將所標(biāo)注的類中所拋出的數(shù)據(jù)訪問異常封裝為Spring的數(shù)據(jù)訪問異常類型乞旦。Spring本身提供了一個(gè)豐富的贼穆,并且是與具體的訪問技術(shù)無關(guān)的數(shù)據(jù)訪問異常結(jié)構(gòu),用于封裝不同的持久層框架所拋出的異常兰粉,使得異常獨(dú)立與底層的框架故痊。
Spring2.5在@Repository的基礎(chǔ)上增加了功能類似的額外三個(gè)注解,總共有如下四種注解:
@Component:一個(gè)泛化的概念玖姑,表示一個(gè)組件(Bean)愕秫,可作用在任何層次
@Controller:用于對(duì)Controller實(shí)現(xiàn)類進(jìn)行標(biāo)注,目前該功能與Component相同
@Repository:用于對(duì)DAO實(shí)現(xiàn)類進(jìn)行標(biāo)注
@Service:用于對(duì)Service實(shí)現(xiàn)類進(jìn)行標(biāo)注焰络,目前該功能與Component相同
這三個(gè)注解除了作用于不同軟件層次的類戴甩,其使用方式與Repository是完全相同的。
2.Bean的生命周期注解在某些情況下闪彼,可能需要我們手工做一些額外的初始化或者銷毀操作甜孤,例如資源的獲取和是否操作,Spring1.x為此提供了兩種方式供用戶指定執(zhí)行生命周期回調(diào)的方法:實(shí)現(xiàn)Spring提供的兩個(gè)接口:initializingBean 和 DisposableBean畏腕,這種方法是要求bean類實(shí)現(xiàn)Spring的接口缴川,但增加了bean和Spring容器的耦合度,因此不推薦使用描馅。在XML文件中使用的init-method 和 destory-method 屬性把夸,指定初始化之后和回調(diào)之前的回調(diào)方法。這兩個(gè)屬性的取值是bean中相應(yīng)的初始化和銷毀方法的名稱铭污。方法名稱任意恋日,但是方法不能有參數(shù)。
示例如下:
在這里嘹狞,我們指定了userService 這個(gè)bean的初始化方法為:init ? ? 銷毀方法為:destory
Spring2.5在保留以上兩種方式的基礎(chǔ)上岂膳,提供了對(duì)JSR-250的支持。
JSR-250規(guī)范定義了兩個(gè)用于指定聲明周期方法的注解:
@PostConstruct:初始化之后的執(zhí)行的回調(diào)方法
@PreDestroy:銷毀之前的回調(diào)方法
注解示例說明:
3.Bean的依賴檢查注解
Spring2.0之前使用dependency-check在配置文件中設(shè)置屬性用于依賴檢查(只會(huì)檢查Setter方法是否被調(diào)用)磅网,缺點(diǎn)是粒度較粗闷营,該屬性的取值包括以下幾種:
none: 默認(rèn)不執(zhí)行依賴檢查
simple :對(duì)原始基本類型和集合類型進(jìn)行檢查
objects :對(duì)復(fù)雜類型進(jìn)行檢查
all :對(duì)所有類型進(jìn)行檢查
使用Spring2.0提供的@Required注解,提供了更細(xì)粒度的控制知市,@Required注解只能標(biāo)注在Setter方法之上,(標(biāo)注在其他方法之上會(huì)被忽略 )用于檢查其是否被調(diào)用速蕊,當(dāng)Setter方法未被調(diào)用的話會(huì)拋出異常嫂丙。
由于使用了注解,所以得激活Bean的后處理器规哲,所以得在XML配置文件當(dāng)中增加
三.基于Java類的配置
基于Java類定義Bean配置元數(shù)據(jù)跟啤,其實(shí)就是通過Java類定義Spring配置元數(shù)據(jù),且直接消除XML配置文件。
首先讓我們看一下基于Java類如何定義Bean配置元數(shù)據(jù)隅肥,具體步驟如下:
使用@Configuration注解需要作為配置的類竿奏,表示該類將定義Bean的元數(shù)據(jù)
使用@Bean注解相應(yīng)的方法,該方法名默認(rèn)就是Bean的名稱腥放,該方法返回值就是Bean的對(duì)象泛啸。
AnnotationConfigApplicationContext或子類進(jìn)行加載基于java類的配置
接下來通過示例來演示下如何基于Java類來配置Spring
首先創(chuàng)建一個(gè)配置類
然后還需要一個(gè)測(cè)試類,來查看配置是否成功
基于Java方式的配置方式不是為了完全替代基于XML方式的配置秃症,兩者可以結(jié)合使用候址,因此可以有兩種結(jié)合使用方式:
在基于Java方式的配置類中引入基于XML方式的配置文件
在基于XML方式的配置文件中中引入基于Java方式的配置
總結(jié):不同配置方式比較
我們來看一下不同配置方式在不同方面的使用
其實(shí)Spring支持這么多的配置方式,那么這些配置方式必然有其自己獨(dú)特的舞臺(tái)
基于XML的配置主要使用場(chǎng)景:
第三方類庫(kù)种柑,如DataSource岗仑、JdbcTemplate等;
命名空間聚请,如aop荠雕、context等;
基于注解的配置主要使用場(chǎng)景:
Bean的實(shí)現(xiàn)類是當(dāng)前項(xiàng)目開發(fā)的驶赏,可直接在Java類中使用注解配置
基于Java類的配置主要使用場(chǎng)景:
對(duì)于實(shí)例化Bean的邏輯比較復(fù)雜炸卑,則比較適合用基于Java類配置的方式
在日常的開發(fā)中我們主要是使用XML配置和注解配置方式向結(jié)合的開發(fā)方式,一般不推薦使用基于Java類的配置方式母市。