Spring的隱式注入

當我們在使用依賴注入的時候,通常有三種方式:

1.通過構造器來注入;

2.通過setter方法來注入;

3.通過filed變量來注入;

Constructor

@Controller
@RequestMapping("/app")
public class APPController {

    private AppService appService;

    public APPController(AppService appService) {
        this.appService = appService;
    }

    @RequestMapping("/out")
    public void out(){
        appService.printf();
    }
}

構造器的隱式注入,在構造器上面無需使用@Autowire註解

Setter

@Controller
@RequestMapping("/app")
public class APPController {

    private AppService appService;

    @Autowired
    public void setAppService(AppService appService) {
        this.appService = appService;
    }

    @RequestMapping("/out")
    public void out(){
        appService.printf();
    }
}

這裏在構造器上面必須使用 @Autowired註解

Field

@Controller
@RequestMapping("/app")
public class APPController {

	@Autowired
    private AppService appService;

    @RequestMapping("/out")
    public void out(){
        appService.printf();
    }
}

測試注入

在這裏插入圖片描述

總結

區別:

1.基於constructor的注入,會固定依賴注入的順序;該方式不允許我們創建bean對象之間的循環依賴關係,這種限制其實是一種利用構造器來注入的益處 - 當你甚至沒有注意到使用setter注入的時候,Spring能解決循環依賴的問題;

2.基於setter的注入,只有當對象是需要被注入的時候它纔會幫助我們注入依賴,而不是在初始化的時候就注入;另一方面如果你使用基於constructor注入,CGLIB不能創建一個代理,迫使你使用基於接口的代理或虛擬的無參數構造函數。

3.相信很多同學都選擇使用直接在成員變量上寫上註解來注入,正如我們所見,這種方式看起來非常好,精短,可讀性高,不需要多餘的代碼,也方便維護;

缺點:

1.當我們利用constructor來注入的時候,比較明顯的一個缺點就是:假如我們需要注入的對象特別多的時候,我們的構造器就會顯得非常的冗餘、不好看,非常影響美觀和可讀性,維護起來也較爲困難;

2.當我們選擇setter方法來注入的時候,我們不能將對象設爲final的;

3.當我們在field變量上來實現注入的時候

a.這樣不符合JavaBean的規範,而且很有可能引起空指針;

b.同時也不能將對象標爲final的;

c.類與DI容器高度耦合,我們不能在外部使用它;

d.類不通過反射不能被實例化(例如單元測試中),你需要用DI容器去實例化它,這更像集成測試;

註解@Configuration

在 Configuration註解的類,裏面可以使用接口名直接注入,不需要@Autowire註解

@Configuration
public class AppConfig {

    @Bean
    public Object setService(AppService appService){
        appService.configuration();
        return new Object();
    }
}

AppService是接口類,啓動項目,容器加載Bean,看是否打印調用:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章