天天看點

深入淺出springboot2.x(3)

依賴注入

前面講了将bean裝配到IOC容器中,但是對于bean之間的依賴沒有涉及,在springioc概念中,我們将其稱為依賴注入(Dependency Injection,DI)

代碼案例,首先定義兩個接口,一個人類一個動物

public interface Person {
    public void service();
    public void setAnimal(Animal animal);
}
           
public interface Animal {
    public void use();
}
           

兩個實作類

@Component
public class BussinessPerson implements Person {
	@Autowired
    private Animal animal= null;
    @Override
    public void service() {
        this.animal.use();
    }

    @Override
    public void setAnimal(Animal animal) {
        this.animal=animal;
    }
}
           
@Component
public class Dog implements Animal {
    @Override
    public void use() {
        System.out.println("狗"+Dog.class.getSimpleName()+"是人類的朋友");
    }
}
           

注解 @Autowired是我們常見的注解之一,它會根據屬性的類型去找到對應的bean進行注入。Dog類是動物的一種,IOC容器會把dog的執行個體注入BussinessPerson中。通過IOC容器擷取BussinessPerson執行個體的時候就能夠使用Dog執行個體來提供服務了。測試代碼

@ComponentScan
public class DIConfig {

    public static void main(String[] args) {
        ApplicationContext ctx = new AnnotationConfigApplicationContext(DIConfig.class);
        Person p = ctx.getBean(BussinessPerson.class);
        p.service();
    }
}
           

輸出結果

狗Dog是人類的朋友
           

@ComponentScan注解後面沒有寫掃描的範圍,預設是掃描目前包下的bean。

注解 @Autowired

@Autowired注解是我們常用的注解之一,它注入的機制最基本的一條是根據類型,在IOC容器中我們是用getBean方法擷取對應bean的,而getBean支援根據類型或根據名稱擷取。接着上面的例子,我們再建立一個動物類----貓

@Component
public class Cat implements Animal {
    @Override
    public void use() {
        System.out.println("貓"+Cat.class.getSimpleName()+"抓老鼠");
    }
}
           

我們還用之前的BussinessPerson類,不過需要注意的是這個類隻定義了一個動物屬性,而我們現在裝配在IOC容器中的有兩個動物,運作之前的測試代碼:

七月 01, 2019 11:06:53 上午 org.springframework.context.support.AbstractApplicationContext refresh
警告: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException:
 Error creating bean with name 'bussinessPerson': Unsatisfied dependency expressed through field 'animal'; 
 nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 
 'springbootall.springboot.spring.springdi3_3.Animal' available: expected single matching bean but found 2: cat,dog
           

從日志中可以看出,IOC容器并不知道你需要注入什麼動物給BussinessPerson類對象,進而引發錯誤。假設目前我們需要的是貓類,那麼需要轉換一下屬性名,把原來的

@Autowired
    private Animal animal= null;
           

修改為

@Autowired
    private Animal cat;
           

我們再測試的時候看到的就是貓提供的服務。 @Autowired會根據類型找到對應的bean,如果對應的類型的bean不是唯一的,那麼它會根據其屬性名稱和bean的名稱進行比對。如果比對的上,就會使用該bean,如果還是無法比對,就會抛異常。