Spring學習Bean配置的三種方式(XML、註解、Java類)介紹與對比

本文將詳細介紹Spring Bean配置的三種不同方式的特點與使用條件。

主要包括:

  • 基於XML的配置方式
  • 基於註解的配置方式
  • 基於Java類的配置方式

一.基於XML的配置

請看Spring學習(十二)Spring 的配置文件概述

二.基於註解的配置

Spring2.0開始引入基於註解的配置方式,即Bean的定義信息可以通過在Bean的實現類上標註註解實現。

具體關於註解的知識請看Java註解(Annotation)介紹

@Component是Spring容器中的基本註解,表示容器中的一個組件(bean),可以作用在任何層次,下面的示例介紹該註解的使用方法。

註解配置示例:


  1. @Component("userDao")
  2. public class userDao{......}

他等效於XML配置

此外,還有一些其他的可以被用來註解bean的註解,這些可以讓註解類本身的用途更加清晰,此外,特定的註解也具備特定的功能。

Spring在2.5後提供了一個context的命名空間,它提供了通過掃描類包來加載利用註解定義的Bean的方式。

在context中可以使用resource-pattern來過濾出特定的類。

默認情況下加載的是package下的*.class即掃描全部類,在使用了resource-pattern之後,則只掃描package下的anno子包下的所有類。

不過使用resource-pattern並不能提供給我們完善的功能,所有我們得使用

過濾子元素的方法。


其中:

include-filter表示要包含的目標類,

exclude-filter表示要排除在外的目標類

一個component-scan標籤下可以有多個include-filter和exclude-filter,

過濾表達式所支持的類型如下表所示:

Spring學習Bean配置的三種方式(XML、註解、Java類)介紹與對比

在這些類型當中,除了Custom外,aspectj的過濾功能最強大,他能輕易的實現其他類別的過濾規則。

Spring3.0提供了一系列的針對依賴注入的註解,這使得Spring IoC在XML文件之外多了一種可行的選擇,主要包含如下註解類型:

  • Bean的定義註解
  • Bean的生命週期註解
  • Bean的依賴檢查註解
  • Bean的自動裝配註解

1.Bean的定義註解

Spring自2.0開始,陸續引入了一些註解用於簡化Spring的開發。

@Repository註解便屬於最先引入的一批,用於將

數據訪問層(DAO層)的類標識為Spring Bean。具體使用如下:

①首先使用@Repository將DAO類聲明為Bean


  1. @Repository
  2. public class UserDaoImpl implements UserDao{......}

②在XML配置文件中啟動Spring的自動掃描功能


  1. ......

如此的話,我們便不在需要在XML當中顯式使用bean來進行bean的配置。Spring容器在初始化的時候便會自動掃描base-package所指定的包以及子包下面的所有class文件。所有標註為Repository的類將被自動註冊為bean。

為什麼Repository只能標註在DAO類上面呢?

因為該註解的作用不只是將類識別為bean,同時他還能將所標註的類中所拋出的數據訪問異常封裝為Spring的數據訪問異常類型。Spring本身提供了一個豐富的,並且是與具體的訪問技術無關的數據訪問異常結構,用於封裝不同的持久層框架所拋出的異常,使得異常獨立與底層的框架。

Spring2.5在@Repository的基礎上增加了功能類似的額外三個註解,總共有如下四種註解:

  • @Component:一個泛化的概念,表示一個組件(Bean),可作用在任何層次
  • @Controller:用於對Controller實現類進行標註,目前該功能與Component相同
  • @Repository:用於對DAO實現類進行標註
  • @Service:用於對Service實現類進行標註,目前該功能與Component相同

這三個註解除了作用於不同軟件層次的類,其使用方式與Repository是完全相同的。

2.Bean的生命週期註解

在某些情況下,可能需要我們手工做一些額外的初始化或者銷燬操作,例如資源的獲取和是否操作,Spring1.x為此提供了兩種方式供用戶指定執行生命週期回調的方法:

  1. 實現Spring提供的兩個接口:initializingBeanDisposableBean,這種方法是要求bean類實現Spring的接口,但增加了bean和Spring容器的耦合度,因此不推薦使用。
  2. 在XML文件中使用init-methoddestory-method
    屬性,指定初始化之後和回調之前的回調方法。這兩個屬性的取值是bean中相應的初始化和銷燬方法的名稱。方法名稱任意,但是方法不能有參數。

示例如下:


  1. init-method="init" destory-method="destory">

在這裡,我們指定了userService 這個bean的初始化方法為:init 銷燬方法為:destory

Spring2.5在保留以上兩種方式的基礎上,提供了對JSR-250的支持。

JSR-250規範定義了兩個用於指定聲明週期方法的註解:

  • @PostConstruct:初始化之後的執行的回調方法
  • @PreDestroy:銷燬之前的回調方法

註解示例說明:


  1. public class PersonService{
  2. @PostConstruct
  3. public void init(){......}
  4. @PreDestory
  5. public void destory(){......}
  6. }

在這裡init方法是初始化之後執行的方法,而destory方法為銷燬之前執行的方法

由於使用了註解,所以得激活Bean的後處理器,所以得在XML配置文件當中增加

3.Bean的依賴檢查註解

Spring2.0之前使用dependency-check

在配置文件中設置屬性用於依賴檢查(只會檢查Setter方法是否被調用),缺點是粒度較粗,該屬性的取值包括以下幾種:

  • none: 默認不執行依賴檢查
  • simple :對原始基本類型和集合類型進行檢查
  • objects :對複雜類型進行檢查
  • all :對所有類型進行檢查

使用Spring2.0提供的@Required註解,提供了更細粒度的控制,@Required註解只能標註在Setter方法之上,(標註在其他方法之上會被忽略 )用於檢查其是否被調用,當Setter方法未被調用的話會拋出異常

由於使用了註解,所以得激活Bean的後處理器,所以得在XML配置文件當中增加

4.Bean的自動裝配註解

@Autowired可以對成員變量、方法和構造函數進行標註,來完成自動裝配的工作,他根據類型進行自動裝配,如果需要按名稱進行裝配,則需要配合@Qualifier使用。

當標註了@Autowired的方法所需的類型在Spring容器中不存在的話會拋出異常


  1. @Service
  2. public class LoginService{
  3. @Autowired
  4. private LogDao logDao;
  5. }

如上面的例子所示,假如Spring容器中沒有LogDao這個bean的話便會拋出異常。

解決的辦法便是使用required=false屬性來標註


  1. public class LoginService{
  2. @Autowired(required=false)
  3. private LogDao LogDao;
  4. }

但是假如Spring當中存在多個所需類型的bean,那麼便要使用@Qualifier註解來指定名稱。


  1. public class LoginService{
  2. @Autowired
  3. @Qualifier("userDao")
  4. private UserDao userDao;
  5. }

@Autowired 可以對類中集合類的變量或方法入參進行標註,此時會將容器中類型匹配的所有Bean都注入進來,如下所示:


  1. public class loginService{
  2. @Autowired(required=false)
  3. public List pligins;
  4. public List getPlugins(){
  5. return plugins;
  6. }
  7. }

Spring會將容器中所有類型為Plugin的bean都注入到集合中去。

三.基於Java類的配置

基於Java類定義Bean配置元數據,其實就是通過Java類定義Spring配置元數據,且直接消除XML配置文件。

首先讓我們看一下基於Java類如何定義Bean配置元數據,具體步驟如下:

  1. 使用@Configuration註解需要作為配置的類,表示該類將定義Bean的元數據
  2. 使用@Bean註解相應的方法,該方法名默認就是Bean的名稱,該方法返回值就是Bean的對象。
  3. AnnotationConfigApplicationContext或子類進行加載基於java類的配置

接下來通過示例來演示下如何基於Java類來配置Spring

首先創建一個配置類


  1. @Configuration
  2. public class ApplicationContextConfig {
  3. @Bean
  4. public String message() {
  5. return "hello";
  6. }
  7. }

然後還需要一個測試類,來查看配置是否成功


  1. public class ConfigurationTest {
  2. public static void main(String[] args) {
  3. AnnotationConfigApplicationContext ctx =
  4. new AnnotationConfigApplicationContext(ApplicationContextConfig.class);
  5. System.out.println(ctx.getBean("message"));
  6. }
  7. }

通過@Configuration註解的類將被作為配置類使用,表示在該類中將定義Bean配置元數據,且使用@Configuration註解的類本身也是一個Bean,使用方式如下所示:


  1. @Configuration("ctxConfig")
  2. public class ApplicationContextConfig {
  3. ……
  4. }

其中Configuration中的參數值即為該bean的名稱

通過@Bean註解配置類中的相應方法,則該方法名默認就是Bean名,該方法返回值就是Bean對象,並定義了Spring IoC容器如何實例化、自動裝配、初始化Bean邏輯,具體使用方法如下:


  1. @Bean(name={},
  2. autowire=Autowire.NO,
  3. initMethod="",
  4. destroyMethod="")

其中name為bean的名稱,可以有多個,autowire為是否自動裝配,默認值為NO,initMethod為bean的初始化方法,destoryMethod為bean的銷燬方法。

bean的註解具體使用如下:


  1. @Bean
  2. public String message() {
  3. return new String("hello");
  4. }

如上的代碼等價與XML配置:


注意使用bean註解的方法不能是private、final、static的。

基於Java方式的配置方式不是為了完全替代基於XML方式的配置,兩者可以結合使用,因此可以有兩種結合使用方式:

  • 在基於Java方式的配置類中引入基於XML方式的配置文件
  • 在基於XML方式的配置文件中中引入基於Java方式的配置

引入基於XML配置文件:


  1. @Configuration("ctxConfig")
  2. @ImportResource("classpath:com/jike/***/appCtx.xml")
  3. public class ApplicationContextConfig {
  4. ……
  5. }

可以看到在java程序中使用@ImportResource導入了XML的配置文件

引入基於Java的配置文件:


  1. //測試類
  2. public void testXmlConfig() {
  3. String configLocations[] = {" classpath:com/jike/***/appCtx.xml"};
  4. ApplicationContext ctx = new ClassPathXmlApplicationContext(configLocations);
  5. ……
  6. }

可以看到在XML的配置文件當中將java的配置類當中Bean來聲明,第一行的是開啟註解驅動支持。

值得注意的是必須得配置在XML配置文件中。

Spring提供了一個AnnotationConfigApplicanContext類,能夠直接通過標註@Configuration的Java類啟動Spring容器:

通過構造函數加載配置類:

ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConf.class);

通過編碼方式註冊配置類:


  1. AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
  2. ctx.register(DaoConfig.class);
  3. ctx.register(ServiceConfig.class);
  4. ctx.refresh();

可以看到ctx註冊了多個configuration類,然後通過refresh類來刷新容器以應用這些配置文件。

可以通過代碼一個個的引入配置類,當然也可以使用@Import註解來引入配置類

引入多個配置類:


  1. @Configuration
  2. @Import(DaoConfig.class)
  3. public class ServiceConfig {……}

總結:不同配置方式比較

我們來看一下不同配置方式在不同方面的使用

Spring學習Bean配置的三種方式(XML、註解、Java類)介紹與對比

其實Spring支持這麼多的配置方式,那麼這些配置方式必然有其自己獨特的舞臺

基於XML的配置主要使用場景:

  • 第三方類庫,如DataSource、JdbcTemplate等;
  • 命名空間,如aop、context等;

基於註解的配置主要使用場景:

  • Bean的實現類是當前項目開發的,可直接在Java類中使用註解配置

基於Java類的配置主要使用場景

  • 對於實例化Bean的邏輯比較複雜,則比較適合用基於Java類配置的方式

在日常的開發中我們主要是使用XML配置註解配置

方式向結合的開發方式,一般不推薦使用基於Java類的配置方式。

Spring學習Bean配置的三種方式(XML、註解、Java類)介紹與對比


分享到:


相關文章: