Bean裝配
- bean裝配有哪幾種方式
- 如何使用javaConfig進行顯示裝配
- 如何使用自動化裝配
什么是裝配
裝配就是創(chuàng)建應(yīng)用對象之間的協(xié)作關(guān)系的行為,也是依賴注入的本質(zhì)蜈缤。
bean的裝配有哪幾種方式
- xml顯式聲明
- java顯式聲明
- 自動裝配的隱式聲明
如何選用裝配方式
- 自動裝配的隱式聲明可以避免大量的顯式聲明代碼柏腻,優(yōu)先推薦使用。
- 但有時無法使用自動裝配時,java的顯式聲明更安全脉漏,更整潔美觀苞冯,功能也更強大。
- 不推薦使用xml的顯式聲明鸠删。
這里只學習自動裝配與java顯式聲明抱完,xml的顯式聲明了解即可
什么是自動裝配
使用組件掃描
和自動裝配
,Spring能夠自動配置Bean并將Bean裝配起來刃泡。
什么是組件掃描
Spring可自動的發(fā)現(xiàn)應(yīng)用上下文所創(chuàng)建的bean
什么是自動裝配
Spring自動滿足bean之間的依賴巧娱。
如何實現(xiàn)組件掃描
- 創(chuàng)建簡單的Bean
- 在Bean類上使用注解@Component,表示該Bean是一個組件類,并告訴Spring要創(chuàng)建這個類的Bean
- 創(chuàng)建一個配置類BeanConfig
- 使用@Configuration注解烘贴,表示該類為配置類禁添。
- 使用@ComponentScan()注解,開啟組件掃描桨踪,自動掃描該類所屬包下所有帶有@Component的類老翘,并自動創(chuàng)建一個Bean
配置類一般和Bean類不在同一個包下,如何掃描其他包下的所有bean類锻离?
在@ComponentScan()中設(shè)置掃描的包:
@ComponentScan(basePackages={"A","B"})
包掃描使用字符串會不會不安全而且不太好管理铺峭?
是的,可以直接指定包中類或接口:
@ComponentScan(basePackageClasses={A.class,B.class})
如何實現(xiàn)自動裝配
通過使用在bean上加上@Autowired注解自動裝配
- 已經(jīng)使用組件掃描或顯式聲明創(chuàng)建好需要裝配的Bean
- 引用需要依賴注入的Bean: private A a
- 在Bean上添加@Autowired注解實現(xiàn)自動裝配
@Autowired注解的作用是什么汽纠?
這個注解的作用是初始化該類時卫键,會自動去獲取聲明的依賴,將其依賴注入進來虱朵。
注意: 如果聲明的依賴bean沒有被創(chuàng)建莉炉,則獲取到的為空。如果聲明的依賴Bean有多個實例碴犬,則會有歧義性絮宁,拋出異常
@Autowired注解使用的是構(gòu)造器注入還是set方法注入?
@Autowired注解支持兩種注解方式服协。
- 構(gòu)造器注入:@Autowired放在構(gòu)造器上绍昂。
- set方式注入:@Autowired放在set方法上或依賴的Bean類上。
- 其他的方式注入:@Autowired可以放在任何方法之上偿荷,只要方法內(nèi)容和set方法一樣即可治专。
通過組件掃描和自動裝配可以隱式的裝配,現(xiàn)在我們來看一個完整例子:
- Animal接口
public interface Animal {
void eat();
}
- Food接口
public interface Food {
String foodName();
}
- Cat類
@Component
public class Cat implements Animal{
@Autowired
private Food food;
public void eat() {
System.out.println("小貓愛吃" + food.foodName());
}
}
- Fash類
@Component
public class Fash implements Food{
public String foodName() {
return "美麗的小金魚";
}
}
- CatConfig配置類
@Configuration
@ComponentScan(basePackageClasses={Cat.class, Fash.class})
public class CatConfig {
}
- CatTest測試類
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=CatConfig.class)
public class CatTest {
@Autowired
private Animal animal;
@Test
public void catTest(){
assertNotNull(this.animal);
this.animal.eat();
}
}
使用@RunWith(SpringJUnit4ClassRunner.class)注解可以加載Juit測試遭顶,使用@ContextConfiguration(classes=CatConfig.class)可以指定加載哪些配置文件
可以看到CatConfig是使用組件掃描的空接口张峰,指定掃描Cat類和Fash類。
Cat類和Fash類都添加了@Component棒旗,掃描到后Spring會創(chuàng)建Bean喘批。
Cat類中依賴了Food,使用@Autowired注解后可以自動裝配Food撩荣,因為組件掃描時已經(jīng)有了Food的bean。
測試類中依賴了一個Animal類饶深,同樣使用@Autowired注解后可以自動裝配餐曹。因為組件掃時創(chuàng)建了Cat的bean
我們基本了解并實現(xiàn)了自動裝配,但自動裝配并不是萬能的敌厘,如果想要為jar中某個類實現(xiàn)自動裝配就不行了台猴。不過,java的顯式聲明是萬能的俱两。
當然饱狂,顯式聲明有java和xml兩種方式,但java更強大類型更安全宪彩,又方便以后重構(gòu)休讳,所以不推薦xml的顯式聲明
如何進行java的顯式聲明:
- 創(chuàng)建普通的java類
- 創(chuàng)建java配置類,使用@Configuration表示該類是一個配置類
- 創(chuàng)建一個生成bean的方法尿孔,只要return一個Bean就行
- 在創(chuàng)建Bean的方法上加上@Bean注解俊柔,Spring會按我們的方法創(chuàng)建一個Bean。
- 若有依賴的類活合,使用構(gòu)造函數(shù)傳入Bean或使用set傳入當前Bean
可以看到雏婶,創(chuàng)建一個生成bean的方法在java中再簡單不過,所以一切java可以做到的東西都可以在創(chuàng)建中做白指。例如初始化尚骄,修改方法名,注入其他的bean類等等侵续。
注意: java配置類應(yīng)單獨放在一個package中,它不應(yīng)和任何業(yè)務(wù)代碼相關(guān)憨闰,分離開來状蜗。
如果所有的關(guān)聯(lián)的bean寫在同一個配置類中,配置類太龐大了鹉动,而且不容易管理吧
是的轧坎,為了處理這種情況,我們應(yīng)該將Bean的聲明分開泽示,并創(chuàng)建一個配置組合類缸血,使用@Import注解將這些配置組合在一起。
我們來看一個詳細完整的例子:
- 創(chuàng)建Animal接口
public interface Animal {
void eat();
}
- 創(chuàng)建Food接口
public interface Food {
String foodName();
}
- 創(chuàng)建Pig類
@Data
public class Pig implements Animal{
@Autowired
private Food food;
@Override
public void eat() {
System.out.println("小豬喜歡" + food.foodName());
}
}
- 創(chuàng)建Meal類
public class Meal implements Food{
@Override
public String foodName() {
return "可口的大米飯";
}
}
- 創(chuàng)建Pig配置類,set注入了Food
@Configuration
public class PigConfig {
@Bean
public Animal pig(Food food){
Pig pig = new Pig();
pig.setFood(food);
return pig;
}
}
- 創(chuàng)建Meal配置類
@Configuration
public class MealConfig {
@Bean
public Food meal(){
return new Meal();
}
}
- 創(chuàng)建配置組合類
@Configuration
@Import({PigConfig.class, MealConfig.class})
public class AnimalConfig {
}
- 8.創(chuàng)建測試類
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={AnimalConfig.class})
public class AnimalTest {
@Autowired
private Animal animal;
@Test
public void pigTest(){
assertNotNull(this.animal);
this.animal.eat();
}
}