1. 程式人生 > >Spring中bean注入初始化方式—通過註解@Configuration @bean

Spring中bean注入初始化方式—通過註解@Configuration @bean

雖然 2.0 版本釋出以來,Spring 陸續提供了十多個註解,但是提供的這些註解只是為了在某些情況下簡化 XML 的配置,並非要取代 XML 配置方式。這一點可以從 Spring IoC 容器的初始化類可以看出:ApplicationContext 介面的最常用的實現類是 ClassPathXmlApplicationContext 和 FileSystemXmlApplicationContext,以及面向 Portlet 的 XmlPortletApplicationContext 和麵向 web 的 XmlWebApplicationContext,它們都是面向 XML 的。

Spring 3.0 新增了另外兩個實現類

:AnnotationConfigApplicationContext 和 AnnotationConfigWebApplicationContext。從名字便可以看出,它們是為註解而生,直接依賴於註解作為容器配置資訊來 源的 IoC 容器初始化類。由於 AnnotationConfigWebApplicationContext 是 AnnotationConfigApplicationContext 的 web 版本,其用法與後者相比幾乎沒有什麼差別,因此本文將以 AnnotationConfigApplicationContext 為例進行講解。 

AnnotationConfigApplicationContext 搭配上 @Configuration 和 @Bean 註解,自此,XML 配置方式不再是 Spring IoC 容器的唯一配置方式。兩者在一定範圍內存在著競爭的關係,但是它們在大多數情況下還是相互協作的關係,兩者的結合使得 Spring IoC 容器的配置更簡單,更強大。 

之前,我們將配置資訊集中寫在 XML 中,如今使用註解,配置資訊的載體由 XML 檔案轉移到了 Java 類中。我們通常將用於存放配置資訊的類的類名以 “Config” 結尾,比如 AppDaoConfig.java、AppServiceConfig.java 等等。我們需要在用於指定配置資訊的類上加上 @Configuration 註解,以明確指出該類是 Bean 配置的資訊源。並且 Spring 對標註 Configuration 的類有如下要求: 

      (a) 配置類不能是 final 的;

      (b)配置類不能是本地化的,亦即不能將配置類定義在其他類的方法內部;

      (c)配置類必須有一個無參建構函式。

AnnotationConfigApplicationContext 將配置類中標註了 @Bean 的方法的返回值識別為 Spring Bean,並註冊到容器中,受 IoC 容器管理。@Bean 的作用等價於 XML 配置中的 標籤。示例如下: 

@Configuration 
public class BookStoreDaoConfig{ 
@Bean 
public UserDao userDao(){ return new UserDaoImpl();} 
@Bean 
public BookDao bookDao(){return new BookDaoImpl();} 

Spring 在解析到以上檔案時,將識別出標註 @Bean 的所有方法,執行之,並將方法的返回值 ( 這裡是 UserDaoImpl 和 BookDaoImpl 物件 ) 註冊到 IoC 容器中。預設情況下,Bean 的名字即為方法名。因此,與以上配置等價的 XML 配置如下:


@Bean 具有以下四個屬性: 

name -- 指定一個或者多個 Bean 的名字。這等價於 XML 配置中 的 name 屬性。

initMethod -- 容器在初始化完 Bean 之後,會呼叫該屬性指定的方法。這等價於 XML 配置中 的 init-method 屬性。

destroyMethod -- 該屬性與 initMethod 功能相似,在容器銷燬 Bean 之前,會呼叫該屬性指定的方法。這等價於 XML 配置中 的 destroy-method 屬性。

autowire -- 指定 Bean 屬性的自動裝配策略,取值是 Autowire 型別的三個靜態屬性。

      1. Autowire.BY_NAME,

       2.Autowire.BY_TYPE,

       3.Autowire.NO。

與 XML 配置中的 autowire 屬性的取值相比,這裡少了 constructor,這是因為 constructor 在這裡已經沒有意義了。@Bean 沒有直接提供指定作用域的屬性,可以通過 @Scope 來實現該功能。

下面講解基於註解的容器初始化。AnnotationConfigApplicationContext 提供了三個建構函式用於初始化容器。 

AnnotationConfigApplicationContext():該建構函式初始化一個空容器,容器不包含任何 Bean 資訊,需要在稍後通過呼叫其 register() 方法註冊配置類,並呼叫 refresh() 方法重新整理容器。

AnnotationConfigApplicationContext(Class... annotatedClasses):這是最常用的建構函式,通過將涉及到的配置類傳遞給該建構函式,以實現將相應配置類中的 Bean 自動註冊到容器中。

AnnotationConfigApplicationContext(String... basePackages):該建構函式會自動掃描以給定的包及其子包下的所有類,並自動識別所有的 Spring Bean,將其註冊到容器中。它不但識別標註 @Configuration 的配置類並正確解析,而且同樣能識別使用 @Repository、@Service、@Controller、@Component 標註的類。

除了使用上面第三種類型的建構函式讓容器自動掃描 Bean 的配置資訊以外,AnnotationConfigApplicationContext 還提供了 scan() 方法,其功能與上面也類似,該方法主要用在容器初始化之後動態增加 Bean 至容器中。呼叫了該方法以後,通常需要立即手動呼叫 refresh() 重新整理容器,以讓變更立即生效。 

需要注意的是,AnnotationConfigApplicationContext 在解析配置類時,會將配置類自身註冊為一個 Bean因為 @Configuration 註解本身定義時被 @Component 標註了。因此可以說,一個 @Configuration 同時也是一個 @Component。大多數情況下,開發者用不到該 Bean,並且在理想情況下,該 Bean 應該是對開發者透明的。@Configuration 的定義如下所示: 
@Target({ElementType.TYPE}) 
@Retention(RetentionPolicy.RUNTIME) 
@Documented 
@Component 
public @interface Configuration { 
String value() default ""; 

}

在一般的專案中,為了結構清晰,通常會根據軟體的模組或者結構定義多個 XML 配置檔案,然後再定義一個入口的配置檔案,該檔案使用 將其他的配置檔案組織起來。最後只需將該檔案傳給 ClassPathXmlApplicationContext 的建構函式即可。

針對基於註解的配置,Spring 也提供了類似的功能,只需定義一個入口配置類,並在該類上使用 @Import 註解引入其他的配置類即可,最後只需要將該入口類傳遞給 AnnotationConfigApplicationContext。具體示例如下: 

@Configuration 
@Import({BookStoreServiceConfig.class,BookStoreDaoConfig.class}) 

public class BookStoreConfig{ … }

混合使用 XML 與註解進行 Bean 的配置 
設計 @Configuration 和 @Bean 的初衷,並不是為了完全取代 XML,而是為了在 XML 之外多一種可行的選擇。由於 Spring 自發布以來,Spring 開發小組便不斷簡化 XML 配置,使得 XML 配置方式已經非常成熟,加上 Spring 2.0 以後出現了一系列名稱空間的支援,使得 XML 配置方式成為了使用簡單、功能強大的 Bean 定義方式。而且,XML 配置的一些高階功能目前還沒有相關注解能夠直接支援。因此,在目前的多數專案中,要麼使用純粹的 XML 配置方式進行 Bean 的配置;要麼使用以註解為主,XML 為輔的配置方式進行 Bean 的配置。 

之所以會出現兩者共存的情況,主要歸結為三個原因:

其一,目前絕大多數採用 Spring 進行開發的專案,幾乎都是基於 XML 配置方式的,Spring 在引入註解的同時,必須保證註解能夠與 XML 和諧共存,這是前提;

其二,由於註解引入較晚,因此功能也沒有發展多年的 XML 強大,因此,對於複雜的配置,註解還很難獨當一面,在一段時間內仍然需要 XML 的配合才能解決問題。

除此之外,Spring 的 Bean 的配置方式與 Spring 核心模組之間是解耦的,因此,改變配置方式對 Spring 的框架自身是透明的。Spring 可以通過使用 Bean 後處理器 (BeanPostProcessor) 非常方便的增加對於註解的支援。這在技術實現上非常容易的事情。

要使用混合配置方式,首先需要判斷以哪一種配置方式為主。對這個問題的不同回答方式將會直接影響到實現的方式。然而大可不必為此傷腦筋,因為不論是以 XML 為主,還是以註解為主,配置方式都是簡單而且容易理解的。這裡不存在錯誤的決定,因為僅僅是表現方式不一樣。我們首先假設以 XML 配置為主的情況。 
對於已經存在的大型專案,可能初期是以 XML 進行 Bean 配置的,後續逐漸加入了註解的支援,這時我們只需在 XML 配置檔案中將被 @Configuration 標註的類定義為普通的 ,同時註冊處理註解的 Bean 後處理器即可。示例如下: 
// 假設存在如下的 @Configuration 類: 
package bookstore.config; 
import bookstore.dao.*; 
@Configuration 
public class MyConfig{ 
@Bean 
public UserDao userDao(){ 
return new UserDaoImpl(); 


此時,只需在 XML 中作如下宣告即可: 

…… 



由於啟用了針對註解的 Bean 後處理器,因此在 ApplicationContext 解析到 MyConfig 類時,會發現該類標註了 @Configuration 註解,隨後便會處理該類中標註 @Bean 的方法,將這些方法的返回值註冊為容器總的 Bean。 
對於以上的方式,如果存在多個標註了 @Configuration 的類,則需要在 XML 檔案中逐一列出。另一種方式是使用前面提到的自動掃描功能,配置如下:

如此,Spring 將掃描所有 demo.config 包及其子包中的類,識別所有標記了 @Component、@Controller、@Service、@Repository 註解的類,由於 @Configuration 註解本身也用 @Component 標註了,Spring 將能夠識別出 @Configuration 標註類並正確解析之。

對於以註解為中心的配置方式,只需使用 @ImportResource 註解引入存在的 XML 即可,如下所示: 
@Configuration 
@ImportResource(“classpath:/bookstore/config/spring-beans.xml”) 
public class MyConfig{ 
…… 

// 容器的初始化過程和純粹的以配置為中心的方式一致: 
AnnotationConfigApplicationContext ctx = 

new AnnotationConfigApplicationContext(MyConfig.class);

相關推薦

Springbean注入初始方式通過註解@Configuration @bean

雖然 2.0 版本釋出以來,Spring 陸續提供了十多個註解,但是提供的這些註解只是為了在某些情況下簡化 XML 的配置,並非要取代 XML 配置方式。這一點可以從 Spring IoC 容器的初始化類可以看出:ApplicationContext 介面的最常用的實現類是

C++11特性:列表初始:VS2010vector的初始方式

        在使用VS2010學習C++Primer第五版時,學習到了初始化的問題,算是一個小難點吧。         C++11的新特性支援列表初始化:將初始值放在花括號(注意不是圓括號)內進行

c++兩種初始方式的區別

首先我們來看一下兩種初始化:int ival(1000);//直接初始化是將初始化式放在括號裡int ival=1000;//複製初始化是用等號(=)那麼這兩種方式有什麼區別呢?我們可以這樣認為,對於內建型別來說,複製初始化和直接初始化幾乎沒有差別,對於類型別來講,當建立類型

SpringBean初始及銷燬方式

Spring中Bean的兩種初始化方式 是什麼 為什麼 但是,如果必須要用多例Bean怎麼辦? 以下為Spring中的多例及初始化 再來說說初始化的一些不同細節 問題: 對Bean的銷

spring原始碼學習(5.1.0版本)——Bean初始

目錄   前言 createBean 有自定義TargetSource代理類的生成 resolveBeforeInstantiation applyBeanPostProcessorsBeforeInstantiation postProcessBeforeIn

Spring-IOC-Bean初始-循環依賴的解決

creation reference single 填充 hash 可能 target get 完美 前言 在實際工作中,經常由於設計不佳或者各種因素,導致類之間相互依賴。這些類可能單獨使用時不會出問題,但是在使用Spring進行管理的時候可能就會拋出BeanCurren

Spring容器啟動 Bean的3種初始方式

通常我們建立一個Bean的時候,可能有這樣的需求,比如我建立了一個連線資料庫的Bean類,我希望在Spring容器建立的時候,就檢查下是否能正常訪問資料庫。這時候我們可以藉助於以下方式進行實現。1、如果

Spring Bean初始和銷燬方式詳解

最近在專案中需要封裝kafka的服務,其中使用到了工廠模式,該模式涉及到了Spring Bean的初始化和銷燬,如是研究了一番,總結如下,和大家共勉之 Spring Bean的初始化和銷燬Bean有幾種方法了?答案是3種 方法一:使用@PostConstruct註解初始化,

Spring bean初始和銷燬三種方式及優先順序

  Spring bean的初始化和銷燬有三種方式   通過實現 InitializingBean/DisposableBean 介面來定製初始化之後/銷燬之前的操作方法;優先順序第二   通過 元素的 init-method/destroy-method屬性指定初始化之

SpringBean初始順序

1.構造程式或者工廠方法建立Bean例項 2.為Bean屬性設定值和Bean引用 3.呼叫感知介面中定義的設定方法 4.將Bean例項傳遞給每個Bean後處理器中的postProcessBeforeI

Spring bean初始和銷燬的三種方式和執行順序

Spring 容器中的 Bean 是有生命週期的,spring 允許 Bean 在初始化完成後以及銷燬前執行特定的操作。 下面是常用的三種指定特定操作的方法: 通過實現InitializingBean/DisposableBean 介面來定製初始化之後/銷燬之前的操作方法;

Springbean的例項方式與IOC容器總結

提到spring,第一印象就是DI與IOC,雖然有概念上的解釋,但是要理解這些概念還是需要動手進行試驗。如果要深入瞭解spring的原來,那麼最先了解得就應該是spring容器。Spring提供了兩種型別的IOC容器實現:      1.beanFactory: IOC 容器

spring ioc容器結構初始步驟以及bean生命週期和三種建立方式

建立物件的三種方式:             1、採用預設的建構函式建立        2、採用靜態工廠方法           1、寫一個靜態工廠方法類                public class HelloWorldFactory {    

Spring IOC 源碼簡單分析 04 - bean初始

-s 示例 classpath 設置 isp 開始 follow spl abs ### 準備 ## 目標 了解 Spring 如何初始化 bean 實例 ##測試代碼 gordon.study.spring.ioc.IOC04_I

Spring Boot實戰筆記(三)-- Spring常用配置(Bean初始和銷毀、Profile)

div nbsp troy string 實例化 public ive work 初始 一、Bean的初始化和銷毀   在我們的實際開發的時候,經常會遇到Bean在使用之前或之後做些必要的操作,Spring對Bean的生命周期操作提供了支持。在使用Java配置和註解配置下提

WCF的ServiceHost初始兩種方式

wcf pre res body BE world typeof OS words 1 代碼方式 using(ServiceHost host=new ServiceHost(typeof(HelloWordService))) { host.AddSe

spring mvc bean初始方法優先級

優先 eth 初始化 接口 定義 str initial mvc 沒有 開始學spring mvc打卡!!! 經過測試得 實現了InitializingBean, DisposableBean接口的初始化方法和銷毀方法優先級最高,但是缺點是不能夠自定義方法名。 自定義的初始

spring源碼-bean初始-1

name art array 形式 framework stat not found object 查看源   一、spring的IOC控制反轉:控制反轉——Spring通過一種稱作控制反轉(IOC)的技術促進了松耦合。當應用了IOC,一個對象依賴的其它對象會通過被動的方式

Spring Bean初始和例項的區別

準確的說,標題中的初始化指的是Bean Definition的初始化,所以是完全不同的兩個概念。   普通的Java類如果想被SpringIOC容器託管,擁有強大的擴充套件功能和更強大的生命週期,使用者(程式設計師)要做的只是寫配置或者寫註解,然後Spring會做這些事:

Spring依賴注入的幾種方式實現鬆耦合

一、普通注入方式: (1)在IDEA工作空間內先建立lib包然後匯入Spring的架包(複製進去的架包要按住滑鼠右鍵出現Add as Library)。 (2)在已經建立好架包的基礎上在src目錄下建立XML檔案,檔案命為applicationContext.xml,需要注意的是我們建