依賴注入
前面講了将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,如果還是無法比對,就會抛異常。