简介
@Resource和@Autowired都是做bean的注入时使用,其实@Resource并不是Spring的注解,它的包是javax.annotation.Resource,但是Spring支持该注解的注入。
本文代码已经上传至 gitee
简单对比
相同点
- 都能进行依赖注入,可以加到属性上也可以加到setter方法上。
不同点
@Autowired注解
- @Autowired注解是按照类型(byType)装配依赖对象,默认情况下它要求依赖对象必须存在,如果允许null值,可以设置它的required属性为false
- @Autowired注解装配对象如果根据类型能匹配到多个,可以通过@Qualifier指定名称通过名称注入。(优先级 高)
- @Autowired注解装配对象如果根据类型能匹配到多个,可以在对应的需要注入的类上添加@Primary注解,来指定默认注入的对象(注意优先级不如@Qualifier)。 (优先级 中)
- @Autowired注解装配对象如果根据类型能匹配到多个,则会按照属性名再去匹配找到对应的bean。(优先级 低)
@Resource注解
- @Resource默认按照ByName自动注入。@Resource有两个重要的属性:name和type,而Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以,如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不制定name也不制定type属性,这时将通过反射机制使用byName自动注入策略。
- 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常
- 如果指定了name,则从上下文中查找名称匹配的bean进行装配,找不到则抛出异常
- 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常
- 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;
代码实战验证
@Autowired验证
// 验证一:@Qualifier注解配合使用
public interface AutowiredInterface {
/**
* 接口方法
*/
void sayAutowired();
}
@Component
@Data
public class AutowiredBean implements AutowiredInterface{
private String name;
@Override
public void sayAutowired() {
System.out.println("autowired:"+name);
}
}
@Component
@Data
public class Autowired02Bean implements AutowiredInterface{
private String name;
@Override
public void sayAutowired() {
System.out.println("autowired:"+name);
}
}
// 不结合 @Qualifier注解,启动直接报错
@Service
public class TestService {
@Autowired
// @Qualifier(value = "autowired02Bean")
private AutowiredInterface autowiredInterface;
public void say() {
System.out.println("开始说。。");
autowiredInterface.sayAutowired();
System.out.println("实际注入的对象:"+autowiredInterface.getClass());
}
}
// 结合 @Qualifier注解,正常启动
@Service
public class TestService {
// value 为指定的bean的名称
@Autowired
@Qualifier(value = "autowired02Bean")
private AutowiredInterface autowiredInterface;
public void say() {
System.out.println("开始说。。");
autowiredInterface.sayAutowired();
System.out.println("实际注入的对象:"+autowiredInterface.getClass());
}
}
// 验证二: @Primary注解结合使用
public interface AutowiredInterface {
/**
* 接口方法
*/
void sayAutowired();
}
@Service
public class TestService {
@Autowired
// @Qualifier(value = "autowired02Bean")
private AutowiredInterface autowiredInterface;
public void say() {
System.out.println("开始说。。");
autowiredInterface.sayAutowired();
System.out.println("实际注入的对象:"+autowiredInterface.getClass());
}
}
@Component
@Data
public class AutowiredBean implements AutowiredInterface{
private String name;
@Override
public void sayAutowired() {
System.out.println("autowired:"+name);
}
}
// 不结合 @Primary 启动报错
@Component
@Data
// @Primary
public class Autowired02Bean implements AutowiredInterface{
private String name;
@Override
public void sayAutowired() {
System.out.println("autowired:"+name);
}
}
// 结合 @Primary 正常启动
@Component
@Data
@Primary
public class Autowired02Bean implements AutowiredInterface{
private String name;
@Override
public void sayAutowired() {
System.out.println("autowired:"+name);
}
}
// 验证三: 通过属性名注入bean
public interface AutowiredInterface {
/**
* 接口方法
*/
void sayAutowired();
}
@Component
@Data
public class AutowiredBean implements AutowiredInterface{
private String name;
@Override
public void sayAutowired() {
System.out.println("autowired:"+name);
}
}
@Component
@Data
// @Primary
public class Autowired02Bean implements AutowiredInterface{
private String name;
@Override
public void sayAutowired() {
System.out.println("autowired:"+name);
}
}
@Service
public class TestService {
// 属性名和具体实现的beanName不一致,启动报错
@Autowired
// @Qualifier(value = "autowired02Bean")
private AutowiredInterface autowiredInterface;
public void say() {
System.out.println("开始说。。");
autowiredInterface.sayAutowired();
System.out.println("实际注入的对象:"+autowiredInterface.getClass());
}
}
// 属性名和具体实现的一致,能成功注入启动
@Service
public class TestService {
// 属性名和具体实现的beanName一致,启动成功
@Autowired
// @Qualifier(value = "autowired02Bean")
private AutowiredInterface autowired02Bean;
public void say() {
System.out.println("开始说。。");
autowired02Bean.sayAutowired();
System.out.println("实际注入的对象:"+autowired02Bean.getClass());
}
}
// 验证四: 验证上述三种的优先级
public interface AutowiredInterface {
/**
* 接口方法
*/
void sayAutowired();
}
@Component
@Data
public class AutowiredBean implements AutowiredInterface{
private String name;
@Override
public void sayAutowired() {
System.out.println("autowired:"+name);
}
}
@Component
@Data
@Primary
public class Autowired02Bean implements AutowiredInterface{
private String name;
@Override
public void sayAutowired() {
System.out.println("autowired:"+name);
}
}
@Component
@Data
public class Autowired03Bean implements AutowiredInterface{
private String name;
@Override
public void sayAutowired() {
System.out.println("autowired:"+name);
}
}
// 接口有三个实现,上面三种分别命中其中的bean,看哪个能具体生效(两个直接的对比只要控制变量即可测出,这里只演示这里,其他自测即可,这里直接给出测出的结果如下: @Qualifier > @Primary > 属性名)
@Service
public class TestService {
@Autowired
@Qualifier(value = "autowiredBean")
private AutowiredInterface autowired03Bean;
public void say() {
System.out.println("开始说。。");
autowired03Bean.sayAutowired();
System.out.println("实际注入的对象:"+autowired03Bean.getClass());
}
}
@Resource验证
//这个验证前面的类可以不变,只要改注入的那部分代码即可,通用代码如下
public interface ResourceInterface {
/**
* 接口方法
*/
void sayResource();
}
@Component
@Data
public class ResourceBean implements ResourceInterface {
private String name;
@Override
public void sayResource() {
System.out.println("resource:"+name);
}
}
@Component
@Data
public class Resource02Bean implements ResourceInterface {
private String name;
@Override
public void sayResource() {
System.out.println("resource:"+name);
}
}
@Component
@Data
public class Resource03Bean implements ResourceInterface {
private String name;
@Override
public void sayResource() {
System.out.println("resource:"+name);
}
}
// 验证一: 既不指定name也不指定type,默认走name,如果没匹配则尝试type,匹配不到报错
@Service
public class TestService {
@Resource
private ResourceInterface resourceInterface;
public void sayResource() {
System.out.println("开始说。。");
resourceInterface.sayResource();
System.out.println("实际注入的对象:"+resourceInterface.getClass());
}
}
// 验证二: 只指定type,默认走name,如果没有或者也多个则报错
@Service
public class TestService {
@Resource(type = ResourceInterface.class)
private ResourceInterface resourceInterface;
public void sayResource() {
System.out.println("开始说。。");
resourceInterface.sayResource();
System.out.println("实际注入的对象:"+resourceInterface.getClass());
}
}
// 验证三: 只指定name,匹配不到报错(spring中的beanName是要唯一的,所以不存在匹配多个)
@Service
public class TestService {
@Resource(name = "hahaha")
private ResourceInterface resourceInterface;
public void sayResource() {
System.out.println("开始说。。");
resourceInterface.sayResource();
System.out.println("实际注入的对象:"+resourceInterface.getClass());
}
}
// 验证四: 既指定name也指定type,默认匹配同时满足的bean,匹配不到报错
@Service
public class TestService {
// 无法匹配
@Resource(name = "hahaha",type = ResourceInterface.class)
private ResourceInterface resourceInterface;
public void sayResource() {
System.out.println("开始说。。");
resourceInterface.sayResource();
System.out.println("实际注入的对象:"+resourceInterface.getClass());
}
}
@Service
public class TestService {
// 无法匹配
@Resource(name = "resourceBean",type = AutowiredInterface.class)
private ResourceInterface resourceInterface;
public void sayResource() {
System.out.println("开始说。。");
resourceInterface.sayResource();
System.out.println("实际注入的对象:"+resourceInterface.getClass());
}
}
@Service
public class TestService {
// 正确匹配
@Resource(name = "resourceBean",type = ResourceInterface.class)
private ResourceInterface resourceInterface;
public void sayResource() {
System.out.println("开始说。。");
resourceInterface.sayResource();
System.out.println("实际注入的对象:"+resourceInterface.getClass());
}
}