@Autowired
在使用spring开发过程中,我们基本上都是使用 @Autowired 这个注解,用来注入已有的 bean。当 spring 中管理两个类型一样的 bean 时,再进行注入时会报错:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.pb.spring.Spring5AutowiredQualifierApplicationTests': Unsatisfied dependency expressed through field 'user3'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.pb.spring.domain.User' available: expected single matching bean but found 2: user1,getUser2
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:586)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)
required 属性
@Autowired(required=true):当使用 @Autowired 注解的时候,其实默认就是@Autowired(required=true),表示注入的时候,该 bean 必须存在,否则就会注入失败。
@Autowired(required=false):表示忽略当前要注入的 bean,如果有直接注入,没有跳过,不会报错。
@Primary
看下面代码,@Primary 表示当遇到系统中有两个User类型时,优先使用 @Primary 注解的这个进行注入。
import com.pb.spring.domain.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
@Configuration
public class UserConfig {
@Bean(name = "user1")
public User getUser1(){
return new User("theodore",25);
}
@Primary
@Bean(name = "user2")
public User user2(){
return new User("james",25);
}
}
import com.pb.spring.domain.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class Spring5AutowiredQualifierApplicationTests {
@Autowired(required = false) //一般在开发环境,不确定是否能注入时用
private User user1;
@Autowired
@Qualifier(value = "user1")
private User user2;
@Autowired
private User user3;
@Test
public void testAuto() {
System.out.println(user2.getName());
System.out.println(user1.getName());
System.out.println(user3.getName());
}
}
@Autowired:spring 中有两种注入方式,by type/by name,@Autowired 使用 byType 注入,当出现两个类型一样的时候,可以显示的用 @Qualifier 指定名称,表明用 by name 方式进行注入。否则会注入 @Primary 那个类。如果没有指定则会报错。 当不确定系统中是否能注入时,可以使用 required=false,不会强制注入。
@Resource
spring 不但支持自己定义的 @Autowired 注解,还支持几个由 JSR-250 规范定义的注解,它们分别是 @Resource、@PostConstruct 以及 @PreDestroy。
@Resource 的作用相当于 @Autowired,只不过 @Autowired 按 byType 自动注入,而 @Resource 默认按 byName 自动注入罢了。@Resource 有两个属性是比较重要的,分是 name 和 type,Spring 将 @Resource 注解的name属性解析为 bean 的名字,而 type 属性则解析为 bean 的类型。所以如果使用 name 属性,则使用 byName 的自动注入策略,而使用 type 属性时则使用 byType 自动注入策略。如果既不指定 name 也不指定 type 属性,这时将通过反射机制使用 byName 自动注入策略。
@Resource 装配顺序
1. 如果同时指定了 name 和 type,则从 Spring 上下文中找到唯一匹配的 bean 进行装配,找不到则抛出异常
2. 如果指定了 name,则从上下文中查找名称(id)匹配的 bean 进行装配,找不到则抛出异常
3. 如果指定了 type,则从上下文中找到类型匹配的唯一 bean 进行装配,找不到或者找到多个,都会抛出异常
4. 如果既没有指定 name,又没有指定 type,则自动按照 byName 方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;
@Autowired 与 @Resource的区别:
1、 @Autowired 与 @Resource 都可以用来装配 bean. 都可以写在字段上,或写在setter方法上。
2、 @Autowired 默认按类型装配(这个注解是属于 spring 的),默认情况下必须要求依赖对象必须存在,如果要允许 null 值,可以设置它的 required 属性为 false,如:@Autowired(required=false) ,如果我们想使用名称装配可以结合 @Qualifier 注解进行使用,如下:
@Autowired()@Qualifier("baseDao")
private BaseDao baseDao;
3、@Resource(这个注解属于 J2EE 的),默认按照名称进行装配,名称可以通过 name 属性进行指定,如果没有指定 name 属性,当注解写在字段上时,默认取字段名进行安装名称查找,如果注解写在 setter 方法上默认取属性名进行装配。当找不到与名称匹配的 bean 时才按照类型进行装配。但是需要注意的是,如果 name 属性一旦指定,就只会按照名称进行装配。
@Resource(name="baseDao")
private BaseDao baseDao;
推荐使用:@Resource 注解在字段上,这样就不用写 setter 方法了,并且这个注解是属于 J2EE 的,减少了与 spring 的耦合。这样代码看起就比较优雅。