@Autowired和@Resource注解的区别和联系
共同点:
都可以通过byType和byName两种方式注入。
没有显示指定时,优先尝试通过一种方式注入,如不成功则切换到另一种方式。
注1:其中byName匹配规则。@Autowired或@Resource指定了name属性,取name属性值。如果没有指定name属性,取注解的字段名(变量名)。
注2:待匹配的bean,如果没有指定自己的name,则默认为类型名的首字母小写形式。例如:@Service public class TestServiceImpl implements TestService,@Service没指定bean的value属性,则注入bean的名字就是类名首字母小写,即"testServiceImpl"。
差异对比:
@Autowired
@Autowired注解是Spring提供的。
@Autowird注解默认优先通过byType方式注入。
@Autowired可通过变量名匹配name。或者配合@Qualifier注解来显式指定name值,如:@Autowired @Qualifier(value = "aServiceImpl")。
@Autowired注解注入的对象需要在IOC容器中存在,否则需要加上属性required=false,表示忽略当前要注入的bean。
@Autowired首先通过byType注入,判断类型。如果有多个实现,无法确定具体是哪一个,则通过byName方式。byName方式如果变量名也无法匹配IOC容器中id,则报错。
@Resource
@Resource注解是J2EE本身提供的。
@Resource可以显示指定byName匹配、byType匹配。或者同时指byType和byName匹配,@Resource(name="aServiceImpl",type=AServiceImpl.class)。
(1)默认情况优先通过byName注入:既不指定@Resource的name属性,也不指定type属性。先通过byName方式查找,找不到与名称匹配的bean时,退回按byType进行查找,如果找到一个就注入。
(2)只指定@Resource注解的name属性,则按name后的名字去bean元素里查找有与之相等的name属性的bean。
(3)只指定@Resource注解的type属性,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常。
(4)既指定了@Resource的name属性又指定了type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常。
按类型匹配,查找到实现类有多个,仍然无法确定的,则报错。
注入过程举例:
接口
public interface TestService { public String test(); }
实现类impl。(没有指定name,则该bean的name为“testServiceImpl”)
@Service public class TestServiceImpl implements TestService { @Override public String test() { return "TestServiceImpl"; } }
Controller的调用:
@RestController public class TestCtl { @Autowired private TestService testService; @RequestMapping("/test") public String test() { return testService.test(); } }
再来说Controller获取实例的过程:
使用@Autowired,程序在spring的容器中查找类型是TestService的bean,刚好找到有且只有一个此类型的bean,即testServiceImpl,所以就把testServiceImpl自动装配到了controller的实例testService中,testService其实就是TestServiceImpl实现类;
如果使用@Resource,则是先在容器中查找名字为testService的bean,但并没有找到,因为容器中的bean名字是testServiceImpl。然后再通过类型查找TestService类型的bean,找到唯一的了个TestService类型bean(即TestServiceImpl),所以就自动装配实例成功了。