Spring Boot簡(jiǎn)明教程--依賴注入的三種方式

官方文檔5.3.3:https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-dependencies

準(zhǔn)備工作

  • 初始化一個(gè)SpringBoot項(xiàng)目
  • 創(chuàng)建pojo包,包下創(chuàng)建Zhangsan、Lisi兩個(gè)實(shí)體類
  • 創(chuàng)建controller包,創(chuàng)建HelloController類
// Zhangsan 
@Component
public class Zhangsan {
    public void say(){
        System.out.println("say hello,i am zhangsan");
    }
}
// Lisi 
@Component
public class Lisi {
    public void say(){
        System.out.println("say hello,i am lisi");
    }
}
// HelloController
@RestController
public class HelloController {
    @GetMapping("/hello")
    public String getHello(){
        return "hello world;";
    }
}

可以看到Zhangsan 、Lisi兩個(gè)類上都打上了@Component注解,該注解將某個(gè)類聲明為一個(gè)Spring的bean, 然后將其加入到Spring容器中,這是實(shí)現(xiàn)注入的前提。(Service、Controller等注解實(shí)現(xiàn)注入同樣依賴于Component注解)

注入方式

Bean的注入通常使用@Autowired注解,該注解用于bean的field、setter方法以及構(gòu)造方法上,顯式地聲明依賴。
在最新的文檔中注入方式有兩大類:

  • 基于構(gòu)造函數(shù)的依賴注入(推薦使用)
  • 基于setter的依賴注入

但是通常認(rèn)為還有一種是基于成員變量的依賴注入(spring framerwork 4.0后不推薦使用)

成員變量注入

public class HelloController {
    @Autowired //idea會(huì)有一個(gè)黃色的波浪線提示Field injection is not recommended(不再推薦使用字段注入)
    private Lisi lisi;
    @GetMapping("/hello")
    public String getHello(){
        lisi.say();
        return "hello world;";
    }
}

構(gòu)造函數(shù)注入

  • 方式一
public class HelloController {

    private Lisi lisi;
    @Autowired //這里的Autowired可以加也可以不加,但是建議加上
    public HelloController(Lisi lisi){
        this.lisi = lisi;
    }
    @GetMapping("/hello")
    public String getHello(){
        lisi.say();
        return "hello world;";
    }
}
  • 方式二
    該方法利用lombok的注解@RequiredArgsConstructor實(shí)現(xiàn)構(gòu)造器注入,需要注意的是要注入的屬性需要加上final修飾
@RequiredArgsConstructor
@RestController
public class HelloController {
//    @Autowired
    private final Lisi lisi;


    @GetMapping("/hello")
    public String getHello(){
        lisi.say();
        return "hello world;";
    }
}

setter注入

public class HelloController {
//    @Autowired
    private Lisi lisi;
    @Autowired
    public void setLisi(Lisi lisi) {
        this.lisi = lisi;
    }

    @GetMapping("/hello")
    public String getHello(){
        lisi.say();
        return "hello world;";
    }
}

拓展 autowired注入形式

首先改造一下我們的項(xiàng)目,將Zhangsan和Lisi兩個(gè)類繼承于Person接口(需要新建),看看運(yùn)行效果

//person
public interface Person {
    void say();
}
//zhangsan lisi
public class Lisi implements Person{
    public void say(){
        System.out.println("say hello,i am lisi");
    }
}
//hellocontroller
@RequiredArgsConstructor
@RestController
public class HelloController {
    private final Person zhangsan;
    @GetMapping("/hello")
    public String getHello(){
        zhangsan.say();
        return "hello world;";
    }
}
  • 情景一,變量聲明為Person person,且只有zhangsan實(shí)現(xiàn)了Person接口,則控制臺(tái)輸出say hello,i am zhangsan
  • 情景二,變量聲明為Person person,zhangsan和lisi同時(shí)實(shí)現(xiàn)了Person接口,則運(yùn)行程序報(bào)錯(cuò)constructor in com.example.controller.HelloController required a single bean, but 2 were found:
  • 情景三,變量聲明為Person lisi,控制臺(tái)輸出say hello,i am lisi
  • 情景四,變量聲明為Person zhangsan,控制臺(tái)輸出say hello,i am zhangsan

上面四個(gè)情景展現(xiàn)了Spring中Autowired的兩種方式

  • byType,默認(rèn)的注入方式,與Bean的屬性具有相同類型的其他Bean自動(dòng)裝配到Bean的對(duì)應(yīng)屬性中。
  • byName,與Bean的屬性具有相同名字的其他Bean自動(dòng)裝配到Bean的對(duì)應(yīng)屬性中

裝配方式總結(jié):

  • 找不到任何一個(gè)bean報(bào)錯(cuò)
  • 一個(gè)會(huì)直接注入
  • 找到多個(gè),不一定會(huì)報(bào)錯(cuò),會(huì)按照字段名注入,如果沒有同名字的bean則報(bào)錯(cuò)

技巧:使用@Qualifier
@Qualifier注解是和@Autowired一起使用的。使用此注解可以讓你對(duì)注入的過程有更多的控制。@Qualifier可以被用在單個(gè)構(gòu)造器或者方法的參數(shù)上。當(dāng)上下文有幾個(gè)相同類型的bean, 使用@Autowired則無法區(qū)分要綁定的bean,此時(shí)可以使用@Qualifier來指定名稱。

//say hello,i am zhangsan
@RestController
public class HelloController {
    @Qualifier("zhangsan")
    @Autowired
    private Person person;
    @GetMapping("/hello")
    public String getHello(){
        person.say();
        return "hello world;";
    }
}
@RequiredArgsConstructor
@RestController
public class HelloController {
    @Qualifier("zhangsan")
    private final Person person;
    @GetMapping("/hello")
    public String getHello(){
        person.say();
        return "hello world;";
    }
}

如果你想同時(shí)使用RequiredArgsConstructor和Qualifier,僅僅寫成下面這樣還是不行的,需要在項(xiàng)目根目錄下新建 lombok.config并寫入

lombok.copyableAnnotations += org.springframework.beans.factory.annotation.Qualifier
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容