@Autowired 和 @Resource 都是 Java 中用于依赖注入的注解
首先它们两个的来源不同
@Autowired是 Spring 框架提供的注解,用于自动装配 bean。@Resource是 Java EE 提供的注解,也可以用于依赖注入,但它更通用,不限于 Spring 框架。@Autowired默认是通过byType的方式注入,如果无法匹配则使用byName的方式注入;而@Resource默认通过byName的方式注入,如果无法匹配则使用byType的方式注入
byName是根据变量名去匹配bean的id属性,而byType则是变量类型去匹配bean的class属性
@Autowired是必须要求装配对象的,如果找不到匹配的 bean,则会抛出异常。@Resource的required属性默认为 true,表示必须装配,但也可以设置为 false,表示如果找不到匹配的 bean,则会将该属性设置为 null,不会抛出异常。
@Resource还有两个重要的属性:name和type,用来显式指定byName和byType方式注入
既没指定name属性,也没指定type属性:默认通过byName方式注入,如果byName匹配失败,则使用byType方式注入
指定name属性:通过byName方式注入,把变量名和IOC容器中的id去匹配,匹配失败则报错
指定type属性:通过byType方式注入,在IOC容器中匹配对应的类型,如果匹配不到或者匹配到多个则报错
同时指定name属性和type属性:在IOC容器中匹配,名字和类型同时匹配则成功,否则失败
下面通过代码一起来看一下 首先定义一个发送信息的Service接口
public interface MessageService {
/**
* 发送信息
* @param message
*/
void sendMessage(String message);
}
它有两个实现类EmailService和SMSService
@Service
public class EmailService implements MessageService {
@Override
public void sendMessage(String message) {
System.out.println("Sending Email: " + message);
}
}
@Service
public class SMSService implements MessageService {
@Override
public void sendMessage(String message) {
System.out.println("Sending SMS: " + message);
}
}
1.使用@Autowired引入bean
当我们尝试在测试类中使用@Autowired引入MessageService并且变量名称使用messageService的时候,idea会报错“有两个类型为MessageSevice的bean无法引入”,编译会报错
这是因为@AutoWired默认是byType的,byType找不到的时候会通过byName,这个name默认是由你的变量名称决定的。这个时候如果我们想继续使用@Autowired引入的时候,有两种方式:
1.将变量的名称修改一下,改成实例bean的id(spring中默认是驼峰命名的)
2.变量名称可以自己定义,使用@Qualifier()来显示的指定name的值
2.使用@Resource注解引入bean
1.当我们不指定它的name的时候,idea不会标红,但是也可以发现它没被注入,因为变量前面没有绿色的标识,同时运行的时候也会报错。这是因为我们没有指定它的name属性而且变量名称取的是service1,它首先会去通过byName去IOC中匹配id为service1的bean,但是没有匹配成功,这时候再通过byType去匹配类型为MessageService的bean,但是找到了两个,所以注入失败了
2.使用@Resource注解,同时指定它们的name,跟上述中的2效果类似