一、@Resource

@Resource是Java自己的注解

先来看一下源码:

java resources怎么弄 java @resource详解_java

@Resource有两个属性是比较重要的,分别是name和type;Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。默认按name进行注入。

下面看一下这样的一个变量注入方式:

java resources怎么弄 java @resource详解_构造函数_02

按type进行注入的自动注入策略,这个type指的就是类的类型,可以这样理解,比如Apple.class,类型就是Apple,Person.class,类型就是Person。

java resources怎么弄 java @resource详解_构造函数_03

如果我有两个Person类,这个时候就无法辨别注入对象,就可以使用name属性去辨别。

在spring中, 被@Component标识的类会在servlet容器启动时加载单实例(默认设置下),用@Resource注解可以注入,如果需要的bean没有被提前加载, 则会报错。

在加载的时,是根据类名(不包括package地址)判断,出现重复的类名会报异常(不在同一个package, 也会报异常)。如果类名相同,可以标识成不同的bean,然后@Resource的name去辨别。

假设,有两个相同的实现类,那么可以用name去辨别,如下:

@Service("a")
public class ReportServiceImpl implements ReportService{
    ......
}

@Service("b")
public class ReportServiceImpl implements ReportService{
    ......
}

注入的时候指定名称为a的那个实现类:

java resources怎么弄 java @resource详解_构造函数_04

这样指定,就知道是哪一个了。

二、@AutoWired

@AutoWired是spring的注解,Autowired只根据type进行注入,不会去匹配name。如果涉及到type无法辨别注入对象时,那需要依赖@Qualifier@Primary注解一起来修饰。@Resource默认按名称方式进行bean匹配,@Autowired默认按类型方式进行bean匹配。

使用@AutoWired变量注解方式时,会有黄色波浪线,idea会提示:

java resources怎么弄 java @resource详解_构造函数_05

Spring团队建议:“在bean中始终使用基于构造函数的依赖注入。始终对强制依赖项使用断言”。

意思是说,用@AutoWired的注入时,尽量用基于构造函数的依赖注入,而不是变量的方式注入。

这就是构造函数方式的依赖注入:

java resources怎么弄 java @resource详解_spring_06

再来看一下@AutoWired注解的源码:

java resources怎么弄 java @resource详解_servlet_07

只有required属性,没有其他属性了,根据type进行注入。

@AutoWired的变量注入时,如果碰到无法分辨的对象,就无法注入成功。但是可以结合@Qualifier注解使用,表明哪个实现类才是我们需要的。

java resources怎么弄 java @resource详解_java_08

但是仍然不建议使用变量注入方式

1、可能会造成NPE,如下:

public class TestController {
 @Autowired
 private TestService testService;
 private String name;
 public TestController(){
  this.name= testService.getName();
 }
 }

这段代码执行时会报NPE。Java类会先执行构造函数,然后在通过@Autowired注入实例,二构造函数里面需要注入的对象,因此在执行构造函数的时候就会报错。

2、还可能回导致循环依赖,即A里面注入B,B里面又注入A。

注:在代码中发现构造方法中注入了很多依赖,显得很臃肿,对于这个问题,说明类中有太多的责任,违反了类的单一性职责原则,这时候需要考虑使用单一职责原则进行代码重构。

三、总结

简单来说,这两的区别就是:

  • @Resource:java的注解,属性较多,type无法分辨时可以用name分辨
  • @Autowired:spring的注解,一个属性,type无法分辨时需要借助@Qualifier注解才能使用,使用@Autowired方式最好使用构造函数的方式注入。

很简单的一个例子,有两个苹果,一个叫哈哈,一个叫呵呵,你指着两个苹果,意思是去拿个苹果,让@Resource去拿,如果不说明,他懵了,但是你说明拿叫哈哈的那个,他就知道了,给你拿来了,让@Autowired去拿,如果不说明,他也懵了,但是他又是个聋子,听不到你说的,结果就拿不到,但是如果写了个字条(@Qualifier)写明拿呵呵,他也就知道了。