Spring框架—— IOC容器和Bean的配置
1 IOC和DI
①IOC(Inversion of Control):反轉控制。
在應用程序中的組件需要獲取資源時,傳統的方式是組件主動的從容器中獲取所需要的資源,在這樣的模式下開發人員往往需要知道在具體容器中特定資源的獲取方式,增加了學習成本,同時降低了開發效率。
反轉控制的思想完全顛覆了應用程序組件獲取資源的傳統方式:反轉了資源的獲取方向——改由容器主動的將資源推送給需要的組件,開發人員不需要知道容器是如何創建資源對象的,只需要提供接收資源的方式即可,極大的降低了學習成本,提高了開發的效率。這種行為也稱為查找的被動形式。
②DI(Dependency Injection):依賴註入
IOC的另一種表述方式:即組件以一些預先定義好的方式(例如:setter 方法)接受來自於容器的資源註入。相對於IOC而言,這種表述更直接。
③IOC容器在Spring中的實現
[1]在通過IOC容器讀取Bean的實例之前,需要先將IOC容器本身實例化。
[2]Spring提供了IOC容器的兩種實現方式
(1)BeanFactory:IOC容器的基本實現,是Spring內部的基礎設施,是面向Spring本身的,不是提供給開發人員使用的。
(2)ApplicationContext:BeanFactory的子接口,提供了更多高級特性。面向Spring的使用者,幾乎所有場合都使用ApplicationContext而不是底層的BeanFactory。
④ApplicationContext的主要實現類
[1]ClassPathXmlApplicationContext:對應類路徑下的XML格式的配置文件
[2]FileSystemXmlApplicationContext:對應文件系統中的XML格式的配置文件
[3]在初始化時就創建單例的bean,也可以通過配置的方式指定創建的Bean是多實例的。
⑤ConfigurableApplicationContext
[1]是ApplicationContext的子接口,包含一些擴展方法
[2]refresh()和close()讓ApplicationContext具有啟動、關閉和刷新上下文的能力。
⑥WebApplicationContext
專門為WEB應用而準備的,它允許從相對於WEB根目錄的路徑中完成初始化工作
2 通過類型獲取bean
從IOC容器中獲取bean時,除了通過id值獲取,還可以通過bean的類型獲取。但如果同一個類型的bean在XML文件中配置了多個,則獲取時會拋出異常,所以同一個類型的bean在容器中必須是唯一的。
HelloWorld helloWorld = cxt.getBean(HelloWorld. class); |
3 給bean的屬性賦值
3.1 賦值的途經
①通過bean的setXxx()方法賦值
HelloWorld中使用的就是這種方式
②通過bean的構造器賦值
<bean id="book" class="com.neuedu.spring.bean.Book" > <constructor-arg value= "10010"/> <constructor-arg value= "Book01"/> <constructor-arg value= "Author01"/> <constructor-arg value= "20.2"/> </bean > |
●通過索引值指定參數位置
<bean id="book" class="com.neuedu.spring.bean.Book" > <constructor-arg value= "10010" index ="0"/> <constructor-arg value= "Book01" index ="1"/> <constructor-arg value= "Author01" index ="2"/> <constructor-arg value= "20.2" index ="3"/> </bean > |
●通過類型不同區分重載的構造器
<bean id="book" class="com.neuedu.spring.bean.Book" > <constructor-arg value= "10010" index ="0" type="java.lang.Integer" /> <constructor-arg value= "Book01" index ="1" type="java.lang.String" /> <constructor-arg value= "Author01" index ="2" type="java.lang.String" /> <constructor-arg value= "20.2" index ="3" type="java.lang.Double" /> </bean > |
③給bean的級聯屬性賦值
<bean id="action" class="com.neuedu.spring.ref.Action"> <property name="service" ref="service"/> <!-- 設置級聯屬性(了解) --> <property name="service.dao.dataSource" value="DBCP"/> </bean> |
④p名稱空間
為了簡化XML文件的配置,越來越多的XML文件采用屬性而非子元素配置信息。
Spring從2.5版本開始引入了一個新的p命名空間,可以通過<bean>元素屬性的方式配置Bean的屬性。
使用p命名空間後,基於XML的配置方式將進一步簡化。
<bean id="studentSuper" class="com.neuedu.helloworld.bean.Student" p:studentId="2002" p:stuName="Jerry2016" p:age="18" /> |
3.2 可以使用的值
①字面量
[1]可以使用字符串表示的值,可以通過value屬性或value子節點的方式指定
[2]基本數據類型及其封裝類、String等類型都可以采取字面值註入的方式
[3]若字面值中包含特殊字符,可以使用<![CDATA[]]>把字面值包裹起來
②null值
<bean class="com.neuedu.spring.bean.Book" id="bookNull" > <property name= "bookId" value ="2000"/> <property name= "bookName"> <null/> </property> <property name= "author" value ="nullAuthor"/> <property name= "price" value ="50"/> </bean > |
③外部已聲明的bean
<bean id="shop" class="com.neuedu.spring.bean.Shop" > <property name= "book" ref ="book"/> </bean > |
④內部bean
當bean實例僅僅給一個特定的屬性使用時,可以將其聲明為內部bean。內部bean聲明直接包含在<property>或<constructor-arg>元素裏,不需要設置任何id或name屬性
內部bean不能使用在任何其他地方
<bean id="shop2" class="com.neuedu.spring.bean.Shop" > <property name= "book"> <bean class= "com.neuedu.spring.bean.Book" > <property name= "bookId" value ="1000"/> <property name= "bookName" value="innerBook" /> <property name= "author" value="innerAuthor" /> <property name= "price" value ="50"/> </bean> </property> </bean > |
3.3 集合屬性
在Spring中可以通過一組內置的XML標簽來配置集合屬性,例如:<list>,<set>或<map>。
①數組和List
配置java.util.List類型的屬性,需要指定<list>標簽,在標簽裏包含一些元素。這些標簽可以通過<value>指定簡單的常量值,通過<ref>指定對其他Bean的引用。通過<bean>指定內置bean定義。通過<null/>指定空元素。甚至可以內嵌其他集合。
數組的定義和List一樣,都使用<list>元素。
配置java.util.Set需要使用<set>標簽,定義的方法與List一樣。
<bean id="shop" class="com.neuedu.spring.bean.Shop" > <property name= "categoryList"> <!-- 以字面量為值的List集合 --> <list> <value> 歷史</value > <value> 軍事</value > </list> </property> <property name= "bookList"> <!-- 以bean的引用為值的List集合 --> <list> <ref bean= "book01"/> <ref bean= "book02"/> </list> </property> </bean > |
②Map
Java.util.Map通過<map>標簽定義,<map>標簽裏可以使用多個<entry>作為子標簽。每個條目包含一個鍵和一個值。
必須在<key>標簽裏定義鍵。
因為鍵和值的類型沒有限制,所以可以自由地為它們指定<value>、<ref>、<bean>或<null/>元素。
可以將Map的鍵和值作為<entry>的屬性定義:簡單常量使用key和value來定義;bean引用通過key-ref和value-ref屬性定義。
<bean id="cup" class="com.neuedu.spring.bean.Cup"> <property name="bookMap"> <map> <entry> <key> <value>bookKey01</value> </key> <ref bean="book01"/> </entry> <entry> <key> <value>bookKey02</value> </key> <ref bean="book02"/> </entry> </map> </property> </bean> |
③Properties(存放鍵值都為類型為String的map)
使用<props>定義java.util.Properties,該標簽使用多個<prop>作為子標簽。每個<prop>標簽必須定義key屬性
<bean class="com.neuedu.spring.bean.DataSource" id="dataSource"> <property name="properties"> <props> <prop key="userName">root</prop> <prop key="password">root</prop> <prop key="url">jdbc:mysql:///test</prop> <prop key="driverClass">com.mysql.jdbc.Driver</prop> </props> </property> </bean> |
④集合類型的bean
如果只能將集合對象配置在某個bean內部,則這個集合的配置將不能重用。我們需要將集合bean的配置拿到外面,供其他bean引用。
配置集合類型的bean需要引入util名稱空間
<util:list id="bookList"> <ref bean="book01"/> <ref bean="book02"/> <ref bean="book03"/> <ref bean="book04"/> <ref bean="book05"/> </util:list>
<util:list id="categoryList"> <value>編程</value> <value>極客</value> <value>相聲</value> <value>評書</value> </util:list> |
4 通過工廠創建bean
4.1 靜態工廠
調用靜態工廠方法創建bean是將對象創建的過程封裝到靜態方法中。當客戶端需要對象時,只需要簡單地調用靜態方法,而不用關心創建對象的細節。
聲明通過靜態方法創建的bean需要在bean的class屬性裏指定靜態工廠類的全類名,同時在factory-method屬性裏指定工廠方法的名稱。最後使用<constrctor-arg>元素為該方法傳遞方法參數。
4.2 實例工廠
實例工廠方法:將對象的創建過程封裝到另外一個對象實例的方法裏。當客戶端需要請求對象時,只需要簡單的調用該實例方法而不需要關心對象的創建細節。
實現方式
①配置工廠類實例的bean
②在factory-method屬性裏指定該工廠方法的名稱
③使用 construtor-arg 元素為工廠方法傳遞方法參數
4.3 FactoryBean
Spring中有兩種類型的bean,一種是普通bean,另一種是工廠bean,即FactoryBean。
工廠bean跟普通bean不同,其返回的對象不是指定類的一個實例,其返回的是該工廠bean的getObject方法所返回的對象。
工廠bean必須實現org.springframework.beans.factory.FactoryBean接口。
<bean id="product" class="com.neuedu.spring.bean.ProductFactory"> <property name="productName" value="Mp3" /> </bean> |
5 bean的高級配置
5.1 配置信息的繼承
①背景
查看下面兩個Employee的配置,其中dept屬性是重復的。
<bean id="dept" class="com.neuedu.parent.bean.Department"> <property name="deptId" value="100"/> <property name="deptName" value="IT"/> </bean>
<bean id="emp01" class="com.neuedu.parent.bean.Employee"> <property name="empId" value="1001"/> <property name="empName" value="Tom"/> <property name="age" value="20"/>
<!-- 重復的屬性值 --> <property name="detp" ref="dept"/> </bean>
<bean id="emp02" class="com.neuedu.parent.bean.Employee"> <property name="empId" value="1002"/> <property name="empName" value="Jerry"/> <property name="age" value="25"/>
<!-- 重復的屬性值 --> <property name="detp" ref="dept"/> </bean> |
②配置信息的繼承
<!-- 以emp01作為父bean,繼承後可以省略公共屬性值的配置 --> <bean id="emp02" parent="emp01"> <property name="empId" value="1002"/> <property name="empName" value="Jerry"/> <property name="age" value="25"/> </bean> |
Spring允許繼承bean的配置,被繼承的bean稱為父bean。繼承這個父bean的bean稱為子bean
子bean從父bean中繼承配置,包括bean的屬性配置
子bean也可以覆蓋從父bean繼承過來的配置
③補充說明
父bean可以作為配置模板,也可以作為bean實例。若只想把父bean作為模板,可以設置<bean>的abstract 屬性為true,這樣Spring將不會實例化這個bean
如果一個bean的class屬性沒有指定,則必須是抽象bean
並不是<bean>元素裏的所有屬性都會被繼承。比如:autowire,abstract等。
也可以忽略父bean的class屬性,讓子bean指定自己的類,而共享相同的屬性配置。但此時abstract必須設為true。
5.2 bean之間的依賴
有的時候創建一個bean的時候需要保證另外一個bean也被創建,這時我們稱前面的bean對後面的bean有依賴。例如:要求創建Employee對象的時候必須創建Department。這裏需要註意的是依賴關系不等於引用關系,Employee即使依賴Department也可以不引用它。
<bean id="emp03" class="com.neuedu.parent.bean.Employee" depends-on="dept"> <property name="empId" value="1003"/> <property name="empName" value="Kate"/> <property name="age" value="21"/> </bean> |
5.3 bean的作用域
在Spring中,可以在<bean>元素的scope屬性裏設置bean的作用域,以決定這個bean是單實例的還是多實例的。
默認情況下,Spring只為每個在IOC容器裏聲明的bean創建唯一一個實例,整個IOC容器範圍內都能共享該實例:所有後續的getBean()調用和bean引用都將返回這個唯一的bean實例。該作用域被稱為singleton,它是所有bean的默認作用域。
當bean的作用域為單例時,Spring會在IOC容器對象創建時就創建bean的對象實例。而當bean的作用域為prototype時,IOC容器在獲取bean的實例時創建bean的實例對象。
5.4 bean的生命周期
①Spring IOC容器可以管理bean的生命周期,Spring允許在bean生命周期內特定的時間點執行指定的任務。
②Spring IOC容器對bean的生命周期進行管理的過程:
[1]通過構造器或工廠方法創建bean實例
[2]為bean的屬性設置值和對其他bean的引用
[3]調用bean的初始化方法
[4]bean可以使用了
[5]當容器關閉時,調用bean的銷毀方法
③在配置bean時,通過init-method和destroy-method 屬性為bean指定初始化和銷毀方法
④bean的後置處理器
[1]bean後置處理器允許在調用初始化方法前後對bean進行額外的處理
[2]bean後置處理器對IOC容器裏的所有bean實例逐一處理,而非單一實例。其典型應用是:檢查bean屬性的正確性或根據特定的標準更改bean的屬性。
[3] bean後置處理器時需要實現接口:
org.springframework.beans.factory.config.BeanPostProcessor。在初始化方法被調用前後,Spring將把每個bean實例分別傳遞給上述接口的以下兩個方法:
●postProcessBeforeInitialization(Object, String)
●postProcessAfterInitialization(Object, String)
⑤添加bean後置處理器後bean的生命周期
[1]通過構造器或工廠方法創建bean實例
[2]為bean的屬性設置值和對其他bean的引用
[3]將bean實例傳遞給bean後置處理器的postProcessBeforeInitialization()方法
[4]調用bean的初始化方法
[5]將bean實例傳遞給bean後置處理器的postProcessAfterInitialization()方法
[6]bean可以使用了
[7]當容器關閉時調用bean的銷毀方法
5.5 引用外部屬性文件
當bean的配置信息逐漸增多時,查找和修改一些bean的配置信息就變得愈加困難。這時可以將一部分信息提取到bean配置文件的外部,以properties格式的屬性文件保存起來,同時在bean的配置文件中引用properties屬性文件中的內容,從而實現一部分屬性值在發生變化時僅修改properties屬性文件即可。這種技術多用於連接數據庫的基本信息的配置。
①直接配置
<!-- 直接配置 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="user" value="root"/> <property name="password" value="root"/> <property name="jdbcUrl" value="jdbc:mysql:///test"/> <property name="driverClass" value="com.mysql.jdbc.Driver"/> </bean> |
②創建properties屬性文件
prop.userName=root prop.password=root prop.url=jdbc:mysql:///test prop.driverClass=com.mysql.jdbc.Driver |
③引入context名稱空間
④指定properties屬性文件的位置
<!-- 指定properties屬性文件的位置 --> <!-- classpath:xxx 表示屬性文件位於類路徑下 --> <context:property-placeholder location="classpath:jdbc.properties"/> |
⑤從properties屬性文件中引入屬性值
<!-- 從properties屬性文件中引入屬性值 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="user" value="${prop.userName}"/> <property name="password" value="${prop.password}"/> <property name="jdbcUrl" value="${prop.url}"/> <property name="driverClass" value="${prop.driverClass}"/> </bean> |
5.6 自動裝配
①自動裝配的概念
[1]手動裝配:以value或ref的方式明確指定屬性值都是手動裝配。
[2]自動裝配:根據指定的裝配規則,不需要明確指定,Spring自動將匹配的屬性值註入bean中。
②裝配模式
[1]根據類型自動裝配:將類型匹配的bean作為屬性註入到另一個bean中。若IOC容器中有多個與目標bean類型一致的bean,Spring將無法判定哪個bean最合適該屬性,所以不能執行自動裝配
[2]根據名稱自動裝配:必須將目標bean的名稱和屬性名設置的完全相同
[3]通過構造器自動裝配:當bean中存在多個構造器時,此種自動裝配方式將會很復雜。不推薦使用。
③選用建議
相對於使用註解的方式實現的自動裝配,在XML文檔中進行的自動裝配略顯笨拙,在項目中更多的使用註解的方式實現。
6 SpEL
6.1 簡介
Spring Expression Language,Spring表達式語言,簡稱SpEL。支持運行時查詢並可以操作對象圖。
和JSP頁面上的EL表達式、Struts2中用到的OGNL表達式一樣,SpEL根據JavaBean風格的getXxx()、setXxx()方法定義的屬性訪問對象圖,完全符合我們熟悉的操作習慣。
6.2 基本語法
SpEL使用#{…}作為定界符,所有在大框號中的字符都將被認為是SpEL表達式。
6.3 使用字面量
●整數:<property name="count" value="#{5}"/>
●小數:<property name="frequency" value="#{89.7}"/>
●科學計數法:<property name="capacity" value="#{1e4}"/>
●String類型的字面量可以使用單引號或者雙引號作為字符串的定界符號
<property name=“name” value="#{‘Chuck‘}"/>
<property name=‘name‘ value=‘#{"Chuck"}‘/>
●Boolean:<property name="enabled" value="#{false}"/>
6.4 引用其他bean
<bean id="emp04" class="com.neuedu.parent.bean.Employee"> <property name="empId" value="1003"/> <property name="empName" value="Kate"/> <property name="age" value="21"/> <property name="detp" value="#{dept}"/> </bean> |
6.5 引用其他bean的屬性值作為自己某個屬性的值
<bean id="emp05" class="com.neuedu.parent.bean.Employee"> <property name="empId" value="1003"/> <property name="empName" value="Kate"/> <property name="age" value="21"/> <property name="deptName" value="#{dept.deptName}"/> </bean> |
6.6 調用非靜態方法
<!-- 創建一個對象,在SpEL表達式中調用這個對象的方法 --> <bean id="salaryGenerator" class="com.neuedu.spel.bean.SalaryGenerator"/>
<bean id="employee" class="com.neuedu.spel.bean.Employee"> <!-- 通過對象方法的返回值為屬性賦值 --> <property name="salayOfYear" value="#{salaryGenerator.getSalaryOfYear(5000)}"/> </bean> |
6.7 調用靜態方法
<bean id="employee" class="com.neuedu.spel.bean.Employee"> <!-- 在SpEL表達式中調用類的靜態方法 --> <property name="circle" value="#{T(java.lang.Math).PI*20}"/> </bean> |
6.8 運算符
①算術運算符:+、-、*、/、%、^
②字符串連接:+
③比較運算符:<、>、==、<=、>=、lt、gt、eq、le、ge
④邏輯運算符:and, or, not, |
⑤三目運算符:判斷條件?判斷結果為true時的取值:判斷結果為false時的取值
⑥正則表達式:matches
7 通過註解配置bean
7.1 概述
相對於XML方式而言,通過註解的方式配置bean更加簡潔和優雅,而且和MVC組件化開發的理念十分契合,是開發中常用的使用方式。
7.2 使用註解標識組件
①普通組件:@Component
標識一個受Spring IOC容器管理的組件
②持久化層組件:@Respository
標識一個受Spring IOC容器管理的持久化層組件
③業務邏輯層組件:@Service
標識一個受Spring IOC容器管理的業務邏輯層組件
④表述層控制器組件:@Controller
標識一個受Spring IOC容器管理的表述層控制器組件
⑤組件命名規則
[1]默認情況:使用組件的簡單類名首字母小寫後得到的字符串作為bean的id
[2]使用組件註解的value屬性指定bean的id
註意:事實上Spring並沒有能力識別一個組件到底是不是它所標記的類型,即使將@Respository註解用在一個表述層控制器組件上面也不會產生任何錯誤,所以@Respository、@Service、@Controller這幾個註解僅僅是為了讓開發人員自己明確當前的組件扮演的角色。
7.3 掃描組件
組件被上述註解標識後還需要通過Spring進行掃描才能夠偵測到。
①指定被掃描的package
<context:component-scan base-package="com.neuedu.component"/> |
②詳細說明
[1]base-package屬性指定一個需要掃描的基類包,Spring容器將會掃描這個基類包及其子包中的所有類。
[2]當需要掃描多個包時可以使用逗號分隔,也可以使用通配符*進行匹配。
[3]如果僅希望掃描特定的類而非基包下的所有類,可使用resource-pattern屬性過濾特定的類,示例:
<context:component-scan base-package="com.neuedu.component" resource-pattern="autowire/*.class"/> |
[4]包含與排除
●<context:include-filter>子節點表示要包含的目標類
註意:通常需要與use-default-filters屬性配合使用才能夠達到“僅包含某些組件”這樣的效果。即:通過將use-default-filters屬性設置為false,禁用默認過濾器,然後掃描的就只是include-filter中的規則指定的組件了。
●<context:exclude-filter>子節點表示要排除在外的目標類
●component-scan下可以擁有若幹個include-filter和exclude-filter子節點
●過濾表達式
類別 |
示例 |
說明 |
annotation |
com.neuedu.XxxAnnotation |
過濾所有標註了XxxAnnotation的類。這個規則根據目標組件是否標註了指定類型的註解進行過濾。 |
assignable |
com.neuedu.BaseXxx |
過濾所有BaseXxx類的子類。這個規則根據目標組件是否是指定類型的子類的方式進行過濾。 |
aspectj |
com.neuedu.*Service+ |
所有類名是以Service結束的,或這樣的類的子類。這個規則根據AspectJ表達式進行過濾。(包括本類) |
regex |
com\.neuedu\.anno\.* |
所有com.neuedu.anno包下的類。這個規則根據正則表達式匹配到的類名進行過濾。 |
custom |
com.neuedu.XxxTypeFilter |
使用XxxTypeFilter類通過編碼的方式自定義過濾規則。該類必須實現org.springframework.core.type.filter.TypeFilter接口 |
③JAR包
必須在原有JAR包組合的基礎上再導入一個:spring-aop-4.0.0.RELEASE.jar
7.4 組件裝配
①需求
Controller組件中往往需要用到Service組件的實例,Service組件中往往需要用到Repository組件的實例。Spring可以通過註解的方式幫我們實現屬性的裝配。
②實現依據
在指定要掃描的包時,<context:component-scan> 元素會自動註冊一個bean的後置處理器:AutowiredAnnotationBeanPostProcessor的實例。該後置處理器可以自動裝配標記了@Autowired、@Resource或@Inject註解的屬性。
③@Autowired註解
[1]根據類型實現自動裝配。
[2]構造器、普通字段(即使是非public)、一切具有參數的方法都可以應用@Autowired註解
[3]默認情況下,所有使用@Autowired註解的屬性都需要被設置。當Spring找不到匹配的bean裝配屬性時,會拋出異常。
[4]若某一屬性允許不被設置,可以設置@Autowired註解的required屬性為 false
[5]默認情況下,當IOC容器裏存在多個類型兼容的bean時,Spring會嘗試匹配bean的id值是否與變量名相同,如果相同則進行裝配。如果bean的id值不相同,通過類型的自動裝配將無法工作。此時可以在@Qualifier註解裏提供bean的名稱。Spring甚至允許在方法的形參上標註@Qualifiter註解以指定註入bean的名稱。
[6]@Autowired註解也可以應用在數組類型的屬性上,此時Spring將會把所有匹配的bean進行自動裝配。
[7]@Autowired註解也可以應用在集合屬性上,此時Spring讀取該集合的類型信息,然後自動裝配所有與之兼容的bean。
[8]@Autowired註解用在java.util.Map上時,若該Map的鍵值為String,那麽 Spring將自動裝配與值類型兼容的bean作為值,並以bean的id值作為鍵。
④@Resource
@Resource註解要求提供一個bean名稱的屬性,若該屬性為空,則自動采用標註處的變量或方法名作為bean的名稱。
⑤@Inject
@Inject和@Autowired註解一樣也是按類型註入匹配的bean,但沒有reqired屬性。
8 泛型依賴註入
8.1 簡介
Spring 4.x中可以為子類註入子類對應的泛型類型的成員變量的引用。
8.2 實現
[1]組件基類
BaseRepository |
public class BaseRepository<T> {
public void save() { System.out.println("Saved by BaseRepository"); }
} |
BaseService |
public class BaseService<T> {
@Autowired private BaseRepository<T> repository;
public void add() { repository.save(); }
} |
[2]組件實體類
UserRepository |
@Repository public class UserRepository extends BaseRepository<User>{
public void save() { System.out.println("Saved by UserRepository"); }
} |
UserService |
@Service public class UserService extends BaseService<User>{
} |
[3]模型實體類
User |
public class User {
} |
[4]測試
ApplicationContext ioc = new ClassPathXmlApplicationContext("di.xml");
UserService us = (UserService) ioc.getBean("userService");
us.add(); |
執行結果 |
Saved by UserRepository |
9 整合多個配置文件
9.1 Spring允許通過<import>將多個配置文件引入到一個文件中,進行配置文件的集成。這樣在啟動Spring容器時,僅需要指定這個合並好的配置文件就可以。
9.2 import元素的resource屬性支持Spring的標準的路徑資源
Spring框架—— IOC容器和Bean的配置