[Spring]04_最小化Spring XML配置


4.1 自動裝配 Bean


Spring 裝配 bean 時,有時非常明確,就是需要將某個 bean 的引用裝配給指定屬性。

例如,若應用上下文中只有一個 javax.sql.DataSource 類型的 bean,那么任意一個依賴 DataSource 的其他 bean 就是需要這個 DataSource Bean。

為了應對這種明確的裝配場景,Spring提供了自動裝配(autowiring)。


4.1.1 四種類型的自動裝配

Spring提供了4種自動裝配策略

(1)byName——把與 Bean 的屬性具有相同名字(或者ID)的其他 Bean 自動裝配到 Bean 的對應屬性中。如果沒有跟屬性的名字相匹配的 Bean, 則該屬性不進行裝配。

(2)byType——把與 Bean 的屬性具有相同類型的其他 Bean 自動裝配到 Bean 的對應屬性中。如果沒有跟屬性的類型相匹配的 Bean,則該屬性不被裝配。

(3)constructor——把與 Bean 的構造器入參具有相同類型的其他 Bean 自動裝配到 Bean 構造器的對應入參中。

(4)autodetect——首先嘗試使用 constructor 進行自動裝配。如果失敗,再嘗試使用 byType 進行自動裝配。

在 Spring 中,使用自動裝配的方式是在 bean 元素中注明 autowire 屬性。

以 byName 為例

假如有一個歌手類,含兩個屬性,一個是演唱的曲目,一個是演奏的樂器。

< bean  id ="jack"  class ="com.spring.demo.Singer" >
     < property  name ="song"  value ="Star"   />
     < property  name ="instrument"  ref ="guitar"   />
</ bean >

以上,是顯示配置 instrument 的方法。

如果,定義定義吉他(Guitar) Bean 時,把 Bean 的 id 屬性設置為 instrument:

< bean  id ="instrument"  class ="com.spring.demo.Guitar"   />

可以發現Guitar Bean的 id 屬性和 Singer Bean 的 name 屬性的名字是一樣的。

Spring 可以通過配置 autowire 屬性,將兩者自動關聯起來,如下:

< bean  id ="jack"  class ="com.spring.demo.Singer"  autowire ="byName" >
     < property  name ="song"  value ="Star"   />
</ bean >

完成。

其他自動裝配類型的使用方式和 byName 差不多,這里不再贅述。


4.1.2 默認自動裝配

你是否會覺得給每一個 bean 都設置相同的 autowire 類型過於麻煩?

Spring允許在根元素 <beans> 上使用 fault-autowire 屬性來設置所有 bean 的默認自動裝配屬性。

<? xml version="1.0" encoding="UTF-8" ?>
< beans  xmlns ="http://www.springframework.org/schema/beans"
    xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance"  
    xsi:schemaLocation
="
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"

    default-autowire
="byType" >
</ beans >

在上例中, <beans> 標簽下的所有 bean 如果不顯示的指定 autowire 屬性,那么它們的默認自動裝配屬性都是 byType 類型。


4.2 使用注解裝配


從 Spring2.5 開始,引入了注解,從此可以使用注解自動裝配 Bean 的屬性。

使用注解方式自動裝配與在XML中使用 autowire 屬性自動裝配並沒有太大區別,但是使用注解方式允許更細粒度的自動裝配。

注意:Spring默認禁用注解裝配,所以要使用它,必須先使用 <context:annotation-config> 來啟用注解配置。

Spring3 支持幾種不同的用於自動裝配的注解:

  • Spring自帶的 @Autowired 注解
  • JSR-330 的 @Inject 注解
  • JSR-250 的 @Resource 注解

4.2.1 @Autowired

對方法進行標注

@Autowired 可以標注需要自動裝配Bean引用的任意方法(set方法、普通方法、構造方法)。


public  class Audience {
     private Movie movie;
    
     //  標注構造方法
    @Autowired
     public Audience(Movie movie) {
         this.movie = movie;
    }

     //  標注set方法
    @Autowired
     public  void setMovie(Movie movie) {
         this.movie = movie;
    }
    
     //  標注構造方法
     public  void watchMovie(Movie movie) {
         this.movie = movie;
        System.out.println("Watch " + movie.toString());
    }
}

對屬性進行標注

可以使用 @Autowired 直接標注屬性,並刪除 setter 方法。


@Autowired
private Movie movie;

@Autowired 不會受限於 private 關鍵字,即使屬性是私有的,它仍然可以被自動裝配。


可選的自動裝配

默認情況下,@Autowired 具有強契約特征,其所標注的屬性或參數必須是可裝配的。

如果沒有 Bean 可以裝配到 @Autowired 所標注的屬性或參數中,自動裝配失敗,拋出 NoSuchBeanDefinitionException

如果,屬性不一定非要裝配,null 值也是可以接受的。這種情況下,可以通過設置 @Autowiredrequired 屬性為 false 來配置自動裝配是可選的。

@Autowired(required= false)
private Movie movie;

注意:require 屬性可以用於 @Autowired 所使用的任意地方。

但是,當使用構造器裝配時,只有一個構造器可以將 @Autowired 的 required 屬性設置為 true,其他的只能置為 false。


@Qualifier

如果有多個 Bean 完全滿足裝配條件,並且都可以被裝配到屬性或參數中。在這種情況下,@Autowired 注解沒有辦法選擇哪一個

Bean 才是真正需要的。這時,可以使用 @Qualifier 注解來縮小選擇范圍。

@Autowired
@Qualifier("cartoon")
private Movie movie;

以上所示,@Qualifier 嘗試注入ID為 cartoon 的 Bean。

 

創建自定義的Qualifier

如下演示了如何自定義一個限定器:

@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @ interface PrivateMovie {
}

有了自定義的注解,就可以用它來代替 @Qualifier:

@Autowired
@PrivateMovie
private Movie movie;

 

4.2.2 @Inject

@Inject 注解是 JSR-330 的核心部件。該注解幾乎可以完全替換 Spring 的 @Autowired 注解。

和 @Autowired 一樣,@Inject 可以用來自動裝配屬性、方法和構造器。

與 @Autowired 不同的是,@Inject 沒有 required 屬性。因此,@Inject 注解所標注的依賴關系必須存在,如果不存在,則會拋出異常。

Provider

JSR-330中有個技巧:不直接注入一個引用,而是注入一個 Provider,Provider 接口可以實現 Bean 引用的延遲注入以及注入 Bean 的多個實例等功能。

 

4.3 自動檢測 Bean


<context:annotation-config> 有助於完全消除 Spring 配置的 <property><constructor-arg> 元素,但是仍然需要使用 <bean> 元素顯示定義 Bean。

<context:component-scan> 除了完成與 <context:annotation-config> 一樣的工作,還允許 Spring 自動檢測 Bean 和定義 Bean。


<? xml version="1.0" encoding="UTF-8" ?>
< beans  xmlns ="http://www.springframework.org/schema/beans"
    xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context
="http://www.springframework.org/schema/context"
    xmlns:util
="http://www.springframework.org/schema/util"
    xmlns:mvc
="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation
="
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
    http://www.springframework.org/schema/context   
    http://www.springframework.org/schema/context/spring-context-3.0.xsd"
>

     < context:component-scan  base-packet ="com.spring.demo" >
     </ context:component-scan >
</ beans >

<context:component-scan> 元素會掃描指定的包及其所有子包,並查找出能夠自動注冊為 Spring Bean 的類。

base-package 屬性標識了 <context:component-scan> 元素所掃描的包。

 

4.3.1 為自動檢測標注 Bean

默認情況下,<context:component-scan> 查找使用構造器注解所標注的類。

這些特殊的注解如下:

  • @Component
  • @Controller
  • @Repository
  • @Service
  • 使用@Component標注的任意自定義注解


4.3.2 過濾組件掃描

<context:component-scan> 中有兩個子元素,可以用來調整掃描行為:

  • <context:include-filter>——包含過濾器
  • <context:exclude-filter>——排除過濾器


< context:component-scan  base-packet ="com.spring.demo" >
     < context:include-filter  type ="assignable"  expression ="com.spring.demo.Movie"   />
</ context:component-scan >

上例中的,typeexpression 屬性一起協作來定義組件掃描策略。

type 有五種選擇:

 

過濾器類型

描述

annotation

過濾器掃描使用指定注解所標注的那些類。通過 expression 屬性指定要掃描的注解

assignable

過濾器掃描派生於 expression 屬性所指定類型的那些類

aspectj

過濾器掃描與 expression 屬性所指定的 AspectJ 表達式所匹配的那些類

custom

使用自定義的org.springframework.core.type.TypeFilter 實現類,該類由 expression 屬性指定

regex

過濾器掃描類的名稱與 expression 屬性所指定的正則表達式所匹配的那些類


參考資料


Spring實戰(第3版)


免責聲明!

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



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