每日一解:Spring Annotations系列之@Autowired

從Spring Framework 2.5開始,引入了一種全新的依賴注入註解@Autowired,這個註解允許Spring自動將被其註釋的Java類注入到Spring 的BeanFactory中。

每日一解:Spring Annotations系列之@Autowired

序言

在本文中,我將基於Spring Boot來演示如何啟用自動注入,以及@Autowired註解各種使用方式。在此係列的文章中,都將採用基於Java的配置方式來配置Spring中的Bean,不再使用基於XML的配置方式。

1. 啟用Annotation

如果你同樣使用了Spring Boot,則可以通過下面的Java代碼配置方式來開啟Annotation支持:

<code>@Configuration
@ComponentScan(basePackages = {"com.ramostear.autowired.annotation.beans"})
public class AppConfig{

}
/<code>

其中,@Configuration作用是告訴Spring這是一個基於Java的配置文件,@ComponentScan則指定Spring進行組件掃描的包路徑。如果你使用基於XML的配置方式,則上述配置代碼等同於下列的配置:

<code>
<beans> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
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">

<component-scan>

/<beans>
/<code>

2. @Autowired註解

開啟Spring註解支持後,你可以將@Autowired註解註釋到類的屬性,Setter方法或構造函數上。Spring會根據@Autowired作用的位置,自動完成目標對象的注入工作。

2.1 @Autowired作用於屬性

當@Autowired註解使用在類的屬性上時,Spring會自動調用屬性的目標類的構造方法,並將最終的實例化對象賦予當前的屬性。下面以電腦,屏幕,鍵盤,鼠標為例子,演示四者之間通過Spring完成自動注入:

<code>@Component
public class Keyboard {

public void working(){
System.out.println("keyboard is working...");
}
}
/<code>
<code>@Component
public class Mouse {

public void working(){
System.out.println("mouse is working...");
}
}
/<code>
<code>@Component
public class Screen {

public void working(){
System.out.println("screen is working...");

}
}
/<code>

說明

@Component註解表示該類是一個被Spring容器所管理的單例Bean組件

接下來,創建一個Computer.java類,並使用@Autowired註解對其屬性進行註釋:

<code>@Component
public class Computer {

@Autowired
private Keyboard keyboard;
@Autowired
private Mouse mouse;
@Autowired
private Screen screen;

public void working(){
screen.working();
keyboard.working();
mouse.working();
System.out.println("computer is working...");
}
}
/<code>

最後,在main方法中測試上述定義的三個組件是否成功注入到Computer類中,並輸出相關的提示語句。在測試代碼中,首先使用AnnotationConfigApplicationContext類獲得應用上下文,然後通過類類型獲得注入到Spring容器中的bean組件。

<code>@SpringBootApplication
public class AutowiredAnnotationApplication {

public static void main(String[] args) {
SpringApplication.run(AutowiredAnnotationApplication.class, args);
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(AppConfig.class);


System.out.println("@Autowired Annotation on field.");
Computer computer = context.getBean(Computer.class);
computer.working();

context.close();

}
}
/<code>

main()方法運行結束後,可在控制檯觀察到如下的輸出語句:

<code>@Autowired Annotation on field.
screen is working...
keyboard is working...
mouse is working...
computer is working...
/<code>

說明

如果@Autowired註解直接作用到屬性上,則當前類在初始化時就需要完成其引用對象的裝配工作。

2.2 @Autowired作用於Setter方法

當在Setter方法上使用@Autowired註解時,Spring會根據對象類型完成組件的自動裝配工作。創建一個新的類MagicBook.java來演示此案例(其餘的類沿用之前案例中的類):

<code>@Component
public class MagicBook {

private Keyboard keyboard;
private Mouse mouse;
private Screen screen;

@Autowired
public void setKeyboard(Keyboard keyboard) {
this.keyboard = keyboard;

}
@Autowired
public void setMouse(Mouse mouse) {
this.mouse = mouse;
}
@Autowired
public void setScreen(Screen screen) {
this.screen = screen;
}

public void working(){
screen.working();
keyboard.working();
mouse.working();
System.out.println("MagicBook is working...");
}
}
/<code>

同樣,在main()方法中編寫對應的代碼進行測試,並觀察控制檯輸出信息。

<code>System.out.println("@Autowired Annotation on setter method.");
MagicBook magicBook = context.getBean(MagicBook.class);
magicBook.working();
/<code>
<code>@Autowired Annotation on setter method.
screen is working...
keyboard is working...
mouse is working...
MagicBook is working...
/<code>

提示

於作用在屬性上不同的是,當@Autowired註解作用在Setter方法上時,在實例化當前類的過程中,不會立即裝配相關的組件,只有在顯示調用Setter方法時Spring才會完成裝配工作。

2.3 @Autowired作用於Constructor

除上述兩種方式外,@Autowired還可以在構造器上使用,在此情況下,當實例化當前對象時,Spring將自動完成組件注入工作。新建一個XPhone.java類演示此案例,並在main()方法中編寫測試代碼,運行並觀察控制檯輸出。

<code>@Component
public class XPhone {
private final Keyboard keyboard;
private final Mouse mouse;
private final Screen screen;

@Autowired
public XPhone(Keyboard keyboard,Mouse mouse,Screen screen){
this.keyboard = keyboard;
this.mouse = mouse;
this.screen = screen;
}

public void working(){
keyboard.working();
mouse.working();
screen.working();
System.out.println("XPhone is working...");
}
}
/<code>
<code>System.out.println("@Autowired Annotation on constructor.");
XPhone xPhone = context.getBean(XPhone.class);
xPhone.working();
/<code>
<code>@Autowired Annotation on constructor.
keyboard is working...
mouse is working...
screen is working...
XPhone is working...
/<code>

注意

如果@Autowired註解作用於構造器上,則該類中有且只有一個構造器可以使用@Autowired註解

3. 其他

3.1 默認配置

當一個類中有且只有一個構造器且使用基於構造器完成組件裝配的情況下,構造器可以不使用@Autowired註解。Spring默認會使用該構造器並根據參數類型完成自動裝配工作。新建一個XWatch.java來演示此案例:

<code>@Component
public class XWatch {
private final Keyboard keyboard;
private final Mouse mouse;
private final Screen screen;

public XWatch(Keyboard keyboard,Mouse mouse,Screen screen){
this.keyboard = keyboard;
this.mouse = mouse;
this.screen = screen;
}

public void working(){
keyboard.working();
mouse.working();
screen.working();
System.out.println("XWatch is working...");
}
}
/<code>

在main()方法中編寫測試代碼,運行main()方法並觀察控制檯輸出:

<code>System.out.println("Single constructor does not use @Autowired annotation.");
XWatch xWatch = context.getBean(XWatch.class);
xWatch.working();
/<code>
<code>Single constructor does not use @Autowired annotation.
keyboard is working...
mouse is working...
screen is working...
XWatch is working...
/<code>

3.2 可選依賴

在使用@Autowired註解時,如果希望某個組件的自動裝配是可選的(非必須),則可以通過下面的方式配置:

<code>@Autowired(required=false)
private DemoComponent demoComponent;
/<code>

本文所涉及的源代碼已上傳到Github,需要的小夥伴可點擊下面的鏈接移步到Github進行下載:


每日一解:Spring Annotations系列之@Autowired

https://github.com/ramostear/spring-annotations-daily-example


分享到:


相關文章: