自动装配:Spring利用依赖注入(DI),完成对IOC容器中各个组件的依赖关系赋值
1 @Autowired
1.1 @Autowired介绍
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
/**
* Declares whether the annotated dependency is required.
* <p>Defaults to {@code true}.
*/
boolean required() default true;
}
- 可以用在构造方法,方法,属性
- 有一个参数: required: 表示是否必须,默认是ture
1.2 演示
- 在AddressService中增加以下定义
分别在在构造方法,属性,set方法加@AutoWired
注解,自动注入Person,AddressDao,UserDao,
@Service
public class AddressService {
@Autowired
private AddressDao addressDao;
private UserDao userDao;
private Person person;
@Autowired
public AddressService(Person person) {
this.person = person;
}
@Autowired
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public AddressDao getAddressDao() {
return addressDao;
}
public UserDao getUserDao() {
return userDao;
}
public Person getPerson() {
return person;
}
@Override
public String toString() {
return "AddressService{" +
"addressDao=" + addressDao +
", userDao=" + userDao +
", person=" + person +
'}';
}
}
- 将UserDao,AddressDao注入到容器中
@Repository
public class AddressDao {
}
@Repository
public class UserDao {
}
- 主配置文件
@Configuration
@ComponentScan(value = {"study.wyy.spring.anno.learn"})
@PropertySource({"classpath:mysql.properties"})
public class MainConfig3 {
@Bean
public Person person() {
return new Person("autoWired", 11);
}
}
- 测试
@Test
public void test02(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig3.class);
AddressService bean = applicationContext.getBean(AddressService.class);
Assert.assertThat(bean.getAddressDao(),notNullValue());
Assert.assertThat(bean.getPerson(),notNullValue());
Assert.assertThat(bean.getUserDao(),notNullValue());
}
- request 属性演示
在主配配置文件中不再注入Person
@Configuration
@ComponentScan(value = {"study.wyy.spring.anno.learn"})
@PropertySource({"classpath:mysql.properties"})
public class MainConfig3 {
}
在测试: 会抛出UnsatisfiedDependencyException
@Test(expected = UnsatisfiedDependencyException.class)
public void test03(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig3.class);
AddressService bean = applicationContext.getBean(AddressService.class);
Assert.assertThat(bean.getAddressDao(),notNullValue());
Assert.assertThat(bean.getPerson(),notNullValue());
Assert.assertThat(bean.getUserDao(),notNullValue());
}
在注入Person的地方,将request设置为false
@Service
public class AddressService {
@Autowired
private AddressDao addressDao;
private UserDao userDao;
private Person person;
public AddressService(@Autowired(required = false)Person person) {
this.person = person;
}
@Autowired
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public AddressDao getAddressDao() {
return addressDao;
}
public UserDao getUserDao() {
return userDao;
}
public Person getPerson() {
return person;
}
@Override
public String toString() {
return "AddressService{" +
"addressDao=" + addressDao +
", userDao=" + userDao +
", person=" + person +
'}';
}
}
在测试
@Test
public void test04(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig3.class);
AddressService bean = applicationContext.getBean(AddressService.class);
Assert.assertThat(bean.getAddressDao(),notNullValue());
Assert.assertThat(bean.getPerson(),nullValue());
Assert.assertThat(bean.getUserDao(),notNullValue());
}
2 @Qualifier
2.1 引入
spring首先会根据类型进行注入,比如刚刚的AddressService中注入了AddressDao,spring默认会先根据类型匹配进行注入,找到AddressDao类型进行注入,如果AddressDao存在多个呢?会根据名字进行再次匹配
进行测试:在主配置在注入一个Person,beanname分别是person
和person2
@Configuration
@ComponentScan(value = {"study.wyy.spring.anno.learn"})
@PropertySource({"classpath:mysql.properties"})
public class MainConfig3 {
@Bean
public Person person() {
return new Person("autoWired", 11);
}
@Bean
public Person person2() {
return new Person("java", 12);
}
}
之前的AddressServie中Person的属性名为person
@Service
public class AddressService {
@Autowired
@Qualifier("addressDao")
private AddressDao addressDao;
private UserDao userDao;
private Person person;
public AddressService(@Autowired(required = false)Person person) {
this.person = person;
}
@Autowired
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public AddressDao getAddressDao() {
return addressDao;
}
public UserDao getUserDao() {
return userDao;
}
public Person getPerson() {
return person;
}
@Override
public String toString() {
return "AddressService{" +
"addressDao=" + addressDao +
", userDao=" + userDao +
", person=" + person +
'}';
}
}
测试 : 注入的person是person2而不是person
@Test
public void test05(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig3.class);
AddressService bean = applicationContext.getBean(AddressService.class);
Assert.assertThat(bean.getAddressDao(),notNullValue());
Assert.assertThat(bean.getPerson(),notNullValue());
Assert.assertThat(bean.getUserDao(),notNullValue());
Assert.assertThat(bean.getPerson().getName(),equalTo("autoWired"));
}
2.2 如何指定注入的Bean呢
如何指定注入的是person呢—> @Qualifier
@Service
public class AddressService {
@Autowired
private AddressDao addressDao;
private UserDao userDao;
private Person person;
public AddressService(@Autowired(required = false) @Qualifier("person2") Person person) {
this.person = person;
}
@Qualifier
也可以用在方法,属性,参数上,可以和@Autowired
搭配使用
3 @Primary
如果容器中同类型的Bean,存在多个Bean,可以使用@Primary
指定哪一个为主要,优先注入
指定person2为主要,其他组件依赖Person时候,会优先注入person2
@Configuration
@ComponentScan(value = {"study.wyy.spring.anno.learn"})
@PropertySource({"classpath:mysql.properties"})
public class MainConfig3 {
@Bean
public Person person() {
return new Person("autoWired", 11);
}
@Bean
@Primary
public Person person2() {
return new Person("java", 12);
}
}
先去掉AddressService的@Qualifier
注解
public class AddressService {
@Autowired
private AddressDao addressDao;
private UserDao userDao;
private Person person;
public AddressService(@Autowired(required = false) Person person) {
this.person = person;
}
此时注入的也是person2
@Test
public void test05(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig3.class);
AddressService bean = applicationContext.getBean(AddressService.class);
Assert.assertThat(bean.getAddressDao(),notNullValue());
Assert.assertThat(bean.getPerson(),notNullValue());
Assert.assertThat(bean.getUserDao(),notNullValue());
Assert.assertThat(bean.getPerson().getName(),equalTo("autoWired"));
}
但是如果使用`@Qualifier`注解指定注入的是person,则注入的就会是person
```java
@Service
public class AddressService {
@Autowired
private AddressDao addressDao;
private UserDao userDao;
private Person person;
public AddressService(@Autowired(required = false) @Qualifier("person") Person person) {
this.person = person;
}
测试
@Test
public void test07(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig3.class);
AddressService bean = applicationContext.getBean(AddressService.class);
Assert.assertThat(bean.getAddressDao(),notNullValue());
Assert.assertThat(bean.getPerson(),notNullValue());
Assert.assertThat(bean.getUserDao(),notNullValue());
Assert.assertThat(bean.getPerson().getName(),equalTo("autoWired"));
}