Spring中bean注入初始化方式—通過註解@Configuration @bean
雖然 2.0 版本釋出以來,Spring 陸續提供了十多個註解,但是提供的這些註解只是為了在某些情況下簡化 XML 的配置,並非要取代 XML 配置方式。這一點可以從 Spring IoC 容器的初始化類可以看出:ApplicationContext 介面的最常用的實現類是 ClassPathXmlApplicationContext 和 FileSystemXmlApplicationContext,以及面向 Portlet 的 XmlPortletApplicationContext 和麵向 web 的 XmlWebApplicationContext,它們都是面向 XML 的。
Spring 3.0 新增了另外兩個實現類
之前,我們將配置資訊集中寫在 XML 中,如今使用註解,配置資訊的載體由 XML 檔案轉移到了 Java 類中。我們通常將用於存放配置資訊的類的類名以 “Config” 結尾,比如 AppDaoConfig.java、AppServiceConfig.java 等等。我們需要在用於指定配置資訊的類上加上 @Configuration 註解,以明確指出該類是 Bean 配置的資訊源。並且 Spring 對標註 Configuration 的類有如下要求:
(a) 配置類不能是 final 的;
(b)配置類不能是本地化的,亦即不能將配置類定義在其他類的方法內部;
(c)配置類必須有一個無參建構函式。
AnnotationConfigApplicationContext 將配置類中標註了 @Bean 的方法的返回值識別為 Spring Bean,並註冊到容器中,受 IoC 容器管理。@Bean 的作用等價於 XML 配置中的 標籤。示例如下:
@Configurationpublic 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{ … }
設計 @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 進行 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 標註類並正確解析之。
@Configuration
@ImportResource(“classpath:/bookstore/config/spring-beans.xml”)
public class MyConfig{
……
}
// 容器的初始化過程和純粹的以配置為中心的方式一致:
AnnotationConfigApplicationContext ctx =
new AnnotationConfigApplicationContext(MyConfig.class);
相關推薦
Spring中bean注入初始化方式—通過註解@Configuration @bean
雖然 2.0 版本釋出以來,Spring 陸續提供了十多個註解,但是提供的這些註解只是為了在某些情況下簡化 XML 的配置,並非要取代 XML 配置方式。這一點可以從 Spring IoC 容器的初始化類可以看出:ApplicationContext 介面的最常用的實現類是
C++11特性:列表初始化:VS2010中vector的初始化方式
在使用VS2010學習C++Primer第五版時,學習到了初始化的問題,算是一個小難點吧。 C++11的新特性支援列表初始化:將初始值放在花括號(注意不是圓括號)內進行
c++中兩種初始化方式的區別
首先我們來看一下兩種初始化:int ival(1000);//直接初始化是將初始化式放在括號裡int ival=1000;//複製初始化是用等號(=)那麼這兩種方式有什麼區別呢?我們可以這樣認為,對於內建型別來說,複製初始化和直接初始化幾乎沒有差別,對於類型別來講,當建立類型
Spring中Bean的初始化及銷燬方式
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屬性指定初始化之
Spring中Bean的初始化順序
1.構造程式或者工廠方法建立Bean例項 2.為Bean屬性設定值和Bean引用 3.呼叫感知介面中定義的設定方法 4.將Bean例項傳遞給每個Bean後處理器中的postProcessBeforeI
Spring bean 的初始化和銷燬的三種方式和執行順序
Spring 容器中的 Bean 是有生命週期的,spring 允許 Bean 在初始化完成後以及銷燬前執行特定的操作。 下面是常用的三種指定特定操作的方法: 通過實現InitializingBean/DisposableBean 介面來定製初始化之後/銷燬之前的操作方法;
Spring中bean的例項化方式與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,需要注意的是我們建