一、自動裝配
使用過Spring框架的都應該很經常的使用一個注解就就是@Autowired
,我們可以通過使用該注解為一個容器中的類自動裝配需要的依賴,現在我們就來復習一下怎么使用@Autowired
注解為來自動裝配依賴吧。
BookController
@Controller
public class BookController {
@Autowired
private BookService bookService;
}
BookService
@Service
public class BookService {
@Qualifier("bookDao")
@Autowired
private BookDao bookDao2;
public void print() {
System.out.println(bookDao2);
}
@Override
public String toString() {
return "BookService{" +
"bookDao=" + bookDao2 +
'}';
}
}
BookDao
@Repository
public class BookDao {
private String lable = "1";
public String getLable() {
return lable;
}
public void setLable(String lable) {
this.lable = lable;
}
@Override
public String toString() {
return "BookDao{" +
"lable='" + lable + '\'' +
'}';
}
}
我們可以看到controller中裝配了service,service中裝配了dao,現在看一下配置類:
@Configuration
@ComponentScan({"com.jiayifan.dao", "com.jiayifan.service", "com.jiayifan.bean"})
public class MainConfigOfAutowired {
}
然后是測試類:
public class IOCTest_Autowired {
@Test
public void test01() {
//1、創建IOC容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAutowired.class);
BookService bookService = applicationContext.getBean(BookService.class);
System.out.println(bookService);
}
}
測試結果:
上面就是@Autowired
注解的最基礎的用法,可是大家可以考慮一下@Autowired
是按照什么樣的規則來幫我們的組件裝配依賴的嗎,我們今天主要就來學習一下怎么控制@Autowired
幫我們裝配依賴。
首先我們需要知道@Autowired
標注的依賴,Spring會先去容器中按照類型進行匹配,如果只找到一個,那么就把找到的組件注入到當前的目標組件中,如果沒有找到的話就會報錯,我們可以通過@Autowired(required = false)
將required
屬性的值設置為false
來消除這種錯誤,因為@Autowired
注解默認當前的依賴是必須的。如果再容器中找到了兩個同樣類型的組件,那么Spring會如何選擇呢,難道是剪刀石頭布嗎?
當然不是,Spring會按照在目標組件中依賴組件的屬性名作為依賴組件的名字來選擇,比如我們在service中依賴的dao屬性名為private BookDao bookDao;
,所以Spring就會把名字為bookDao
的組件注入service,我們當然也可以自己制定這種選擇的規則,下面我們就來看一下如何實現吧:
首先配置類:
@Configuration
@ComponentScan({"com.jiayifan.dao", "com.jiayifan.service", "com.jiayifan.bean"})
public class MainConfigOfAutowired {
@Bean("bookDao2")
public BookDao bookDao() {
BookDao bookDao = new BookDao();
bookDao.setLable("2");
return bookDao;
}
}
我們可以發現我們即使用了包掃描,又在配置類中使用@Bean
注解添加了一個dao組件,現在容器中有兩個dao組件,一個名字是bookDao
,另一個名字是bookDao2
,而servcie中的屬性名為bookDao
,現在我們就像使用bookDao2
,我們就可以通過在service中使用@Qualifier("bookDao2")
注解來指定我們想要那個組件當做依賴:
@Service
public class BookService {
@Qualifier("bookDao2")
@Autowired()
private BookDao bookDao;
public void print() {
System.out.println(bookDao);
}
@Override
public String toString() {
return "BookService{" +
"bookDao=" + bookDao +
'}';
}
}
測試一下:
我們看到兩個不同的dao中的
lable
屬性是不同的,現在service中的daoi是bookDao2
。我們同樣可以使用一個
@Primary
注解來選擇首要的組件:
@Configuration
@ComponentScan({"com.jiayifan.dao", "com.jiayifan.service", "com.jiayifan.bean"})
public class MainConfigOfAutowired {
@Primary
@Bean("bookDao2")
public BookDao bookDao() {
BookDao bookDao = new BookDao();
bookDao.setLable("2");
return bookDao;
}
}
@Qualifier("bookDao2")
注解的優先級是比@Primary
要高的。
通過上面的學習我們已經了解了在容器中有多個同類型組件的情況下怎么自己選擇需要的依賴,其實感覺并不是很有用,因為感覺還是容器中只有一個組件的情況比較多。
我們通常會把@Autowired
注解標注到屬性上面,其實@Autowired
還可以標注到其他的地方,我們來看一下:
- 通過將@Autowired標注到set方法上,可以實現自動裝填
- 通過將@Autowired標注到相應的有參構造器上,可以實現自動裝填,如果相應組件只有一個有參構造器,注解可以省略
- 通過將@Autowired標注到set方法和有參構造器的參數上,可以實現自動裝填
二、加載外部配置文件
我們在使用Spring的過程中難免要使用到外部的配置文件,比如我們經常講數據庫的連接參數放到properties文件中,我們現在就來學習一下怎么使用注解加載外部配置文件,然后獲取外部配置文件中的值吧,首先我們的配置類:
@PropertySource(value = {"classpath:person.properties"})
@Configuration
public class MainConfigOfPropertyValue {
@Bean
public Person person() {
return new Person();
}
}
我們使用了@PropertySource(value = {"classpath:person.properties"})
注解來加載外部的配置文件,然后我們看一下如何調用配置文件中的值,我們這里有一個組件類:
public class Person {
//使用@Value賦值
//1、基本數值 2、SpEL #{} 3、可以寫${},取出配置文件(properties配置文件)中的值
@Value("張三")
private String name;
@Value("#{20 - 2}")
private Integer age;
@Value("${person.nickName}")
private String nickName;
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
public Person() {
}
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", nickName='" + nickName + '\'' +
'}';
}
}
我們使用@Value
注解來調用配置文件中的值。
測試類:
public class IOCTest_PropertyValue {
@Test
public void test01() {
//1、創建IOC容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfPropertyValue.class);
printBeans();
System.out.println("====================");
Person person = (Person) applicationContext.getBean("person");
System.out.println(person);
}
private void printBeans() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for(String name : beanDefinitionNames) {
System.out.println(name);
}
}
}
測試結果: