Spring學習筆記之一----基於XML的Spring IOC配置


1. 在spring配置文件中,如果對一個property進行直接賦值,可使用<value>元素,spring負責將值轉化為property指定的類型;也可以直接在property元素上使用value屬性來賦值;

2. 構造函數注入,應使用<constructor-arg>元素來賦值,該元素有三個屬性,你可以指定來對賦值的構造函數參數進行區分:type、index或者name,但是當你使用name屬性時,你應該放置@ConstructorProperties annotation到構造函數上去顯式的指定構造函數參數名;

3. spring中對於同名的bean,后一個會覆蓋前一個;

4. 對於指定bean的名字,可以通過<bean>的id屬性,也可以通過name屬性,id屬性只能指定一個名字,name屬性可以指定多個,並且用逗號隔開;

5. 如果通過property注入,我們可以在schema上加上xmlns:p="http://www.springframework.org/schema/p",那么就可以在bean元素上直接加上p:propertyName="value"來進行賦值;同理,通過constructor來注入,則必須加上xmlns:c="http://www.springframework.org/schema/c"的schema,並在bean元素上加上c:argumentName="value"來賦值;

6. 我們在加載一個spring的配置文件,應該使用GenericXmlApplicationContext類,默認該類從classpath下面去加載配置文件;GenericXmlApplicationContext類的某個構造函數接受多個配置文件作為一個字符串的數組;

7. 為了引用其他的bean,你可以使用<ref bean="bean name"/>元素,ref元素中的bean屬性可以引用到其他任何一個配置文件中的bean,如果只想引用相同xml文件中的bean,我們應該使用<ref local="bean name"/>,我們也可以在property元素或者constructor-arg元素上使用ref屬性來引用其他的bean;對於schema,我們可以使用p:propertyName-ref="bean name"來引用其他的bean;

8. <bean/>元素的autowire屬性,默認情況下只用於這個bean所有properties的autowire,它包含3個可能的值:

byName: 根據bean的屬性名找到相同名的bean;

byType: 根據bean的屬性類型找到相同類型的bean;

constructor: 用於bean的構造函數的autowire,它首先根據構造函數的參數類型找到相同類型的bean,然后再確定最佳的構造函數;

當使用autowire byType的時候,如果存在相同類型的多個bean,就會拋異常,那么可以在某一個bean的<bean>元素上加上primary="true",則這個bean在autowire byType時會優先使用;

對於autowire的bean屬性,如果spring找不到響應的bean,那么spring就會設置一個null值;在用戶使用該屬性的時候,可能會得到NullPointerException異常;如此我們可以使用以下兩種方法來規避:

a. 為某個property創建一個setter方法,並使用@Required annotation;

b. 為某個property加上@Autowired annotation,隱式的包涵了@Required;

對於某些bean,我們不想讓其被其他bean autowire,我們可以在這個<bean>元素上加上autowire-candidate="false";

9. 我們可以在一個配置文件中,使用<import>標記去引用其他的配置文件;

10. spring提供了3個元素去定義集合:<list>、<set>、<map>;

對於集合<list>和<set>,其中的item可以是:<value>、<ref>、<bean>、<idref>、<null/>等元素;

對於<map>,其中的item必須是<entry>元素,<entry>元素中的key必須放在<key>元素下,value直接放在<entry>元素下面;無論是key或者value的值,可以是<value>、<ref>、<bean>、<idref>、<null/>元素中的任何一種;<entry>元素也包含有key、value、key-ref、value-ref等屬性;

spring為java.util.Properties集合提供了<props>元素,該元素中的每一個item都必須是<prop>元素,該<prop>元素包含有key屬性;

11. 對於上面提到的創建集合所使用的元素,他們不能被使用來創建一個獨立的bean,如果要創建一個獨立的bean,我們必須要使用util schema,我們需要加入xmlns:util="http://www.springframework.org/schema/util",並且在xsi:schemaLocation中加入http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd;然后我們就可以使用<util:list>、<util:set>、<util:map>來創建集合bean,這三種元素都提供了list-class、set-class、map-class屬性來指定要創建集合的類型;

12. <bean>元素有一個scope屬性,用來指定創建的bean實例的作用域;值可能是:

singleton: 在這個spring容器里面只有一個實例;

prototype: 每一次請求都會創建一個新的bean實例;

request: 每一次請求創建一個新的實例,在Web Application中有效;

session: 每一個session創建一個新的實例,在Web Application中有效;

global-session: 對每一個global HTTP session創建一個新的實例,在Web Application中有效;

13. 為了加載一個property文件進入spring容器,並讓其他bean使用;spring提供了PropertySourcesPlaceholderConfigurer類,它的location屬性用來指定property文件的位置;

然后我們就可以在配置文件中使用${key:default_value}方式來引用property文件中的property;

如果我們要讀取一個文件的內容,spring提供了一個Resource類型,你只需在配置文件中將一個字符串賦值給這個類型的屬性,spring容器會自動將其轉換為Resource實例,這個字符串可以根據文件的不同位置指定不同的前綴,比如文件系統中的文件,就以file開始,classpath中的文件就以classpath開始;如果實在classpath中的一個特殊的包中,可以使用這樣的形式來指定Resource:classpath:com/apress/springrecipes/shop/banner.txt;

 14. 為了讓Spring支持多語言化,Spring提供了通過特定的local去properties文件讀取message的方式,這些message必須被放在properties文件里面,這樣的文件被叫做resource bundle,這些文件應該被放置在classpath 的根目錄下,並且文件名必須遵守messages_<language_code>_<country_code>.properties這樣的約束,我們可以創建一個ReloadableRsourceBundleMessageSource的bean去讀取message,但是由於必須讓Application Context知道這是一個讀取message的bean,所以這個bean的名字必須是messageSource,這個bean的basenames屬性resource bundle文件的文件名(不包含language code和country code部分);

在Spring context中,如果一個bean需要使用到這些message,則需要把messageSource bean注入到那個bean里面;

15. Spring Container中bean的生命周期:

  • 通過構造函數或者工廠方法創建bean實例;
  • 設置bean的屬性值;
  • 調用bean的初始化方法;
  • 使用bean;
  • 當container被關閉時;調用析構器方法;

在bean的定義中,初始化方法和析構器方法都是通過<bean/>元素的init-method和detory-method來指定的;

16. 一般而言,spring context中的所有bean會在Spring Container被啟動后立即執行初始化;為了避免某些過渡消耗時間和資源的bean的創建,我們可以在這樣的<bean>元素上設置lazy-init="true"屬性;

17. 某些時候,一些bean要依賴自另外一些bean被創建后,才能被創建(兩者之間可能並沒有引用的關系);我們可以使用<bean/>元素的depends-on屬性,該屬性可以指定一個或多個bean names,並用逗號隔開;

18. 我們可能想在Spring Container中的每一個bean的初始化方法被調用之前或者之后執行一些任務,比如做一些屬性驗證等;我們可以創建一個類,並使之繼承自BeanPostProcessor接口;

並實現該接口中的postProcessBeforeInitialization方法和postProcessAfterInitialization方法;這樣bean的生命周期就成為:

  • 通過構造函數或者工廠方法創建bean實例;
  • 設置bean的屬性值;
  • 將bean實例傳遞給BeanPostProcessor實現類的postProcessBeforeInitialization方法;
  • 調用bean的初始化方法;
  • 將bean實例傳遞給BeanPostProcessor實現類的postProcessAfterInitialization方法;
  • 使用bean;
  • 當container被關閉時;調用析構器方法;

BeanPostProcessor實現類必須被申明在spring配置文件中;

19. 除開Spring Container實現bean實例的初始化之外,Spring還提供了其他三種方式去創建Bean:

  • 靜態工廠方法;
  • 實例工廠方法;
  • Spring FactoryBean

如果你想利用靜態工廠方法來創建bean實例,你需要在<bean/>節點中通過class屬性指定靜態類的類型,在factory-method屬性中指定方法名,然后通過<constructor-arg/>子元素傳入方法參數;

如果你要使用實例工廠方法,你需要在<bean/>節點上通過factory-bean指定工廠方法所在的bean name,在factory-method屬性中指定方法名,然后通過<constructor-arg/>子元素傳入方法參數;

如果你要利用FactoryBean來創建bean實例,你需要繼承AbstractFactoryBean抽象類,並復寫createInstance()方法去創建目標bean實例,為了讓其他的bean能autowire這個bean,還得實現getObjectType()方法去返回目標bean的類型;

每一次Spring Container去請求FactoryBean,得到的都是目標bean的實例,要想得到FactoryBean本身,需要在bean name前加上&符號;

20. 如果想根據不同的環境給予bean不同的初始值,你可以創建多個具有相同名字的bean,然后把它們放在不同的profile中,每一個profile都通過<beans/>元素的指定,<beans/>元素的profile屬性說明了profile的名字;每一個<beans/>元素可以包含多個bean,也可以為其profile指定多個名字,並用逗號分割開來;

為了在Spring Container啟動時指定加載哪一個profile,你可以通過以下3種方式來做到:

  • 在加載配置文件之前,調用GenericXmlApplicationContext類的getEnvironment().setActiveProfiles("","")
  • 在運行之前,傳入JVM參數-Dspring.profiles.active="XXX,XXX"
  • 為war包的web.xml文件中的servlet傳入spring.profiles.active初始化參數:
<servlet>
 <servlet-name>dispatcher</servlet-name>
 <servlet-class>
   org.springframework.web.servlet.DispatcherServlet
 </servlet-class>
 <init-param>
   <param-name>spring.profiles.active</param-name>
   <param-value>XXX</param-value>
 </init-param>
</servlet>

有時候,為了防止用戶忘記指定profiles導致出錯,我們還可以指定DefaultProfiles:

  • 調用GenericXmlApplicationContext類的getEnvironment().setDefaultProfiles("","")
  • 傳入JVM參數-Dspring.profiles.default="XXX,XXX"
  • 為war包的web.xml文件中的servlet傳入spring.profiles.default初始化參數:
<servlet>
 <servlet-name>dispatcher</servlet-name>
 <servlet-class>
   org.springframework.web.servlet.DispatcherServlet
 </servlet-class>
 <init-param>
   <param-name>spring.profiles.default</param-name>
   <param-value>winter</param-value>
 </init-param>
</servlet>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM