1. 程式人生 > >Spring自動裝配Bean——xml方式與註解方式

Spring自動裝配Bean——xml方式與註解方式

自動裝配的概念

在Spring使用中,我們在xml配置檔案通過元素或元素的ref屬性向bean注入另外的依賴bean。
如果使用自動裝配(autowiring) ,就可以減少甚至消除配置元素和元素。

設定元素的autowire屬性就可以設定bean的自動裝配模式。自動裝配有5種模式。
在這裡插入圖片描述

注意:自動裝配功能和手動裝配要是同時使用,那麼自動裝配就不起作用。


在xml中使用自動裝配

首先假設User類有兩個setter方法,一個是setUsername(),一個是setAccount()。
byName方式

<bean id="ac_100" class="twm.demo.Account"/>

<bean id="user" class="twm.demo.User">
  <property name="username" value="Yanglan"/>
  <property name="account" ref="ac_100"/>
</bean>

<!--以下是使用自動裝配,假設這裡定義的id為account-->
<bean id="account" class="twm.demo.Account"/>

<bean id="user" class="twm.demo.User" autowire="byName">
  <property name="username" value="Yanglan"/>
</bean>

我們看看上下兩種配置的方式的區別,user bean的屬性account的值是一個定義好的Bean,在屬性中通過ref引用其id(ac_100)實現注入。
第二種方式把該Bean的id改成了與引用它的Bean屬性相同的名字(id=”account” 可忽略屬性首字每大小寫),然後使用byName的方式來自動裝配,對user bean來說省略配置一個元素。

byType方式

<bean id="ac_anyname" class="twm.demo.Account"/>
<bean id="user" class="twm.demo.User" autowire="byType">
  <property name="username" value="Yanglan"/>
</bean>

把autowire屬性值改為byType後,在注入account屬性時,並不關心bean id了,而是查詢容器中是否有型別為twm.demo.Account的bean。但是如果有多個bean的型別都匹配的情況,那麼就會出錯,因為byType方式只允許匹配一個型別相同的Bean。

如果在容器中存在多個型別相同的bean怎麼辦呢?spring提供了另外兩種選擇,可以設定一個首選bean,或者排除一些bean。
元素的primary屬性代表是否是首選bean,如果標註為true,那麼該bean將成為首選bean。
但是spring預設每個bean的primary屬性都是true,所以如果需要設定首選bean需要將那些非首選bean的primary屬性標註為false。

<bean id="account" class="twm.demo.Account"/>
<bean id="account_ent" class="twm.demo.Account" primary="false" />

constructor構造方式

<bean id="yanglan" class="twm.demo.User" autowire="constructor">
</bean>

構造器自動裝配只需要把autowire屬性設定為constructor就可以了,這樣就免去了宣告元素

autodetect最佳自動裝配

<bean id="yanglan" class="twm.demo.User" autowire="autodetect">
</bean>

首先使用constructor方式進行裝配,如果不行,就使用byType方式裝配。使用方法跟以上介紹的都是一樣的 ,這裡不多說了

預設自動裝配
在元素中新增一個default-autowire屬性,該配置檔案當中的所有bean將會進行自動裝配,如果有特定的bean需要使用其他的方式,在該bean上直接設定autowire屬性就可以了,會覆蓋掉預設自動裝配的配置,程式碼如下。

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

自動裝配侯選者
XML配置中預設所有的bean都是自動裝配的侯選者。如果設定元素的autowire-candidate屬性為false,該bean將不用於自動裝配。autowire-candidate預設值為true。

元素的default-autowire-candidates屬性的值允許使用萬用字元,例如我們制定default-autowire-candidates=“*abc”,則所有以“abc”結尾的Bean都將被包含到自動裝配的待選類中。該屬性可以指定多個匹配字串,匹配任一字串的Bean都將作為侯選者。


使用註解自動裝配

如果不想在xml檔案中使用autowire屬性來啟用自動裝配,還可以直接在類定義中使用@Autowired或@Resource來裝配bean。

在使用註解裝配之前,首先要開啟註解裝配的方式,在配置檔案中加上下面這句話

<context:annotation-config>

當然還要在xml檔案新增context名稱空間並指定schema

<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:context="http://www.springframework.org/schema/context" 
    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.xsd
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-4.2.xsd">

spring支援多種註解裝配的方式,這裡主要介紹spring自帶的Autowired註解裝配

注:@Resource也可用於自動裝配。但@Resource並不是Spring的註解,他的包是javax.annotation.Resource。Spring支援該註解的注入,@Resource通過設定可以按byName和byType 方式注入,如果都沒有寫,預設按byName方式。

1、使用@Autowired註解
@Autowired註解可以用在任何方法上,不一定非得是setter方法,只要方法有需要自動裝配的引數都可以,但是一般都是使用在setter方法和構造器上的。

注意:@Autowired註解預設使用的是byType的方式向Bean裡面注入相應的Bean。

1.1、用於setter方法:看如下程式碼:

@Autowired
public void setNotifyservice(NotifyService notifyservice) {
    this.notifyservice = notifyservice;
}

以上程式碼是把@Autowired註解在setter方法上,在spring建立該類的bean的時候,就會自動尋找匹配的引數注入到該bean當中。

1.2、用於建構函式:
@Autowired另外一個用法就是註解建構函式:

public class Order {
@Autowired
public Order(NotifyService notifyservice) {
    this.notifyservice = notifyservice;
}
//......省略部分程式碼

1.3、直接註解在屬性(最常用):
@Autowired還有一種用法就是直接註解在屬性上,從而去掉setter方法

@Autowired
private NotifyService notifyservice;

使用@Autowired自動裝配時,容器中只能有一個適合的Bean待選,否則的話,spring會丟擲異常。(因為@Autowired預設是使用byType的方式裝配)
如果在應用上下文當中找不到相應的bean去自動裝配,那麼spring也會丟擲異常(NoSuchBeanDefinitionException)。
如果想避免這種情況發生,而且需要裝配的屬性也不是必須要裝配的話,可以使用如下程式碼來使用註解:

@Autowired(required=false)
private Instrument instrument;

在這裡新增@Autowired的required屬性,將這個屬性設定為false,意思就是在建立bean的時候該屬性不是必須的

2、@Qualifier註解

剛才提到,如果在容器中出現了兩個適合的bean,就會出錯。怎麼解決呢?這個時候可以使用@Qualifier註解指定一個Bean來裝配,這樣就不會報異常了。@Qualifier註解採用的是byName的方式。

@Autowired
@Qualifier("CellPhoneNotifyserviceImpl")
private NotifyService notifyservice;

括號中的字串標註的是需要自動裝配進來的Bean的id 在註解注入中使用表示式

**3、@Value註解 **
在使用註解自動裝配的過程當中,如果想要自動裝配基本型別的或者是字面值常量的引數的話,可以是用@Value註解

@Value("Messi")
private String username;

上例為一個String型別的屬性裝配了一個String型別的值,同樣可以裝配int,boolean等基本型別的屬性。
在@Value註解中,還可以使用表示式來動態的計算並裝配屬性的值。(經常用來從properties檔案中獲取值)
比如使用spel表示式從某個物件屬性中取得一個值()

@Value("#{systemConfig.UploadPath}")
private String savePath;