自动装配即为Spring利用依赖注入来完成对IOC容器中各个组件的依赖关系赋值。
Spring框架的五种自动装配模式:
从Spring2.5开始,开始支持使用注解来自动装配Bean的属性。它允许更细粒度的自动装配,我们可以选择性的标注某一个属性来对其应用自动装配。Spring支持几种不同的应用于自动装配的注解。
@Autowired注解默认优先按照类型(byType)去容器中找对应的组件。如果找到多个相同类型的组件,就将属性的名称作为组件的id去容器中查找同id的bean再进行赋值。
@Autowired注解可以标注在构造器,参数,方法,属性上。标注在方法位置可以不加@Autowired注解,方法参数是直接从容器中获取的。(即为constructor自动装配模式)
下面通过一个例子来掌握@Autowired的作用:
创建Dao层person类
@Repository
public class PersonDao {
public int flag=1;
@Override
public String toString() {
return "PersonDao [flag=" + flag + "]";
}
}
创建service层的personService类
@Service
public class PersonService {
@Autowired
PersonDao personDao;
@Override
public String toString() {
return "PersonService [personDao=" + personDao + "]";
}
}
这里的PersonService 类还可以将@Autowired标注在不同的地方:属性对应的set方法和构造方法。同样能实现将personDao类型的组件装配到PersonService类中。
@Service
public class PersonService {
PersonDao personDao;
@Override
public String toString() {
return "PersonService [personDao=" + personDao + "]";
}
public PersonService(@Autowired PersonDao personDao) {
this.personDao=personDao;
}
}
}
@Service
public class PersonService {
PersonDao personDao;
@Override
public String toString() {
return "PersonService [personDao=" + personDao + "]";
}
@Autowired
public void setPersonDao(PersonDao personDao) {
this.personDao=personDao;
}
}
创建配置类SpringConfigOfAutoWired类
@Configuration
@ComponentScan(value = {
"com.learn.dao","com.learn.service"})
public class SpringConfigOfAutoWired {
@Bean
PersonDao personDao2() {
PersonDao personDao = new PersonDao();
personDao.flag=2;
return personDao;
}
}
创建测试类AutoWiredTest
public class AutoWiredTest {
@Test
public void test() {
//获取Spring的IOC容器
AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext(SpringConfigOfAutoWired.class);
//从容器中获取bean
String[] names= applicationContext.getBeanDefinitionNames();
for(String i:names) {
System.out.println(i);
}
PersonService service=applicationContext.getBean(PersonService.class);
System.out.println(service);
}
}
运行test()方法,查看控制台结果:
可以看到@Autowired默认注入的是personDao,对应属性名personDao。
默认情况下,它具有强制契约特性,其所标注的属性必须是可装配的。当容器中没有这个类型的组件但又不想影响容器的创建,可以使用@Autowired(required = false)
。
另外,当容器中有多个相同类型的组件时,如果定义的这个属性名在容器中没有对应的组件id,那么就会报NoUniqueBeanDefinitionException
这个异常。这时使用@Qualifier注解就可以避免这种情况。
@Qualifier注解的作用是指定需要装配的组件的id,相当于按照byName类型进行自动装配。 @Qualifier不能单独使用。
在 PersonService 类中添加注解@Qualifier("personDao2")
,这样就指定了使用id为personDao2的组件来装配。
@Service
public class PersonService {
@Qualifier("personDao2")
@Autowired
PersonDao personDao3;
@Override
public String toString() {
return "PersonService [personDao=" + personDao3 + "]";
}
}
让Spring进行自动装配时,优先使用@Primary注解修饰的组件。使用这个注解也能避免使用属性名作为id来查找容器中的组件,下面删除前面添加的@Qualifier注解,在person2()方法上添加@Primary
@Configuration
@ComponentScan(value = {
"com.learn.dao","com.learn.service"})
public class SpringConfigOfAutoWired {
@Primary
@Bean(value = "personDao2")
PersonDao personDao2() {
PersonDao personDao = new PersonDao();
personDao.flag=2;
return personDao;
}
}
这样自动装配时就会优先装配id为personDao2的组件。
@Resource属于java规范中的注解,@Resource可以与@Autowired一样实现自动装配功能,默认是按照属性名的名称进行装配。可以通过@Resource(name = “”)指定组件的id,如果byName方式找不到,就使用byType方式查找。但是不支持搭配@Primary和@Qualifier("")使用和不支持@Autowired的required功能。
修改类PersonService 改用@Resource进行自动装配
@Service
public class PersonService {
//@Qualifier("personDao2")
//@Autowired(required = false)
@Resource
PersonDao personDao3;
@Override
public String toString() {
return "PersonService [personDao=" + personDao3 + "]";
}
}
这样也是能成功装配组件。这里如果添加@Primary和@Qualifier("")来指定组件,虽然不会报错但是是不起作用的。
@Inject属于java规范中的注解,同样提供与@Autowired一样实现自动装配功能,支持搭配@Primary和@Qualifier("")注解使用,但是没有支持required=false的功能。
@Inject是根据类型进行自动装配的,找到后以属性名作为id来匹配要装配的组件,如果存在多个相同类型的组件时或需要按名称进行装配,则需要配合@Named;
需要在pom.xml中添加以下依赖才能使用:
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
@Service
public class PersonService {
//@Qualifier("personDao2")
//@Autowired(required = false)
//@Resource
@Named("personDao2")
@Inject
PersonDao personDao3;
@Override
public String toString() {
return "PersonService [personDao=" + personDao3 + "]";
}
}
这样同样能成功装配PersonDao类型的id为personDao2的组件。
@Autowired是spring自带的,@Resource是JSR-250规范实现的,@Inject是JSR-330规范实现的,需要对应导入不同的包。
@Autowired、@Inject用法基本一样,不同的是@Autowired有一个request属性
@Autowired、@Inject是默认按照类型匹配的,@Resource是按照名称匹配的
@Autowired如果需要按照名称匹配需要和@Qualifier一起使用,@Inject和@Name一起使用
@Inject支持搭配@Primary和@Qualifier("")注解一起使用
参考:annotation之@Autowired、@Inject、@Resource三者区别
拓展阅读:
彻底搞明白Spring中的自动装配和Autowired
XML配置文件中实现自动装配——Spring 自动装配及其注解