@Resource与@Autowired注解的区别

发布时间 2023-08-28 14:53:25作者: 角刀牛Java

前言
1、什么是byName和byType
简单来说,byName就是根据变量名去匹配bean的id属性,而byType则是根据变量类型去匹配bean的class属性。实例说明:

<bean id="userService" class="com.test.UserServiceImpl"></bean>
@Autowired
private UserService userService;

此处byName就是拿变量名userService去匹配IOC容器的id为userService的bean,而byType就是拿变量类型UserService去匹配IOC容器的id为com.test.UserService.UserServiceImpl的bean,这里可以匹配成功是因为UserServiceImpl是UserService的实现类。

2、@Resource与@Autowired都是用来调用已经注入到IOC容器中的bean的。

一、@Resource
1、java中自带的注解 (javax.annotation.Resource)
2、默认按照名称(byName)方式进行bean装配,也可以按类型(byType)装配 
3、@Resource的作用范围:类、成员变量、方法
4、@Resource的使用
步骤:@Resource默认通过byName注入,如果没有匹配则通过byType注入。

@Service
public class UserServiceImpl1 implements UserService

@Service
public class UserServiceImpl2 implements UserService

@Resource
private UserService userService;

首先默认通过byName匹配,变量名userService无法匹配IOC容器中任何一个id(因为这里UserService有两个实现类,也就对应有相应的两个bean,即userServiceImpl1和userServiceImpl2),于是再通过byType匹配,发现类型UserService的实现类是两个,仍然无法确定,于是报错。
这时候就要提到@Resource两个重要的属性:name和type,它们用来显式指定byName和byType方式。
显示指定去匹配那个bean时,主要有以下四种情况:

// 1. 默认方式:byName 即不显示指定
@Resource
private UserService userDao;

// 2. 显示指定byName
@Resource(name="userService")
private UserService userService;

// 3. 显示指定byType
@Resource(type=UserService.class)
private UserService userService;

// 4. 显示指定byName和byType
@Resource(name="userService",type=UserService.class)
private UserService userService;

①既没指定name属性,也没指定type属性:默认通过byName方式注入,如果byName匹配失败,则使用byType方式注入(也就是上面的那个例子)
②指定name属性:通过byName方式注入,把变量名和IOC容器中的id去匹配,匹配失败则报错
③指定type属性:通过byType方式注入,在IOC容器中匹配对应的类型,如果匹配不到或者匹配到多个则失败报错
④同时指定name属性和type属性:在IOC容器中匹配,名字和类型同时匹配则成功,否则失败报错。

二、@Autowired
1、Spring自带的注解(org.springframework.beans.factory.annotation.Autowired)
2、默认按照类型(byType)方式进行bean装配,也可以按名称(byName)装配,需要结合@Qualifier如:@Autowired @Qualifier("manImpl")
3、默认要求装配的bean对象必须在IOC容器中存在,如果不存在会报错但不影响正常使用;若允许bean对象不存在,可设置@Autowired(required = false) 。即表示忽略当前要注入的bean,如果有直接注入,没有则跳过,也不会报错了
4、@Autowired的作用范围:成员变量、构造器、方法、参数、注解
5、@Autowired的使用
步骤:@Autowird默认的注入方式为byType,也就是根据类型匹配,当有多个实现时,则通过byName注入,也可以通过配合@Qualifier注解来显式指定name值,指明要使用哪个具体的实现类。

@Service
public class UserServiceImpl1 implements UserService

@Service
public class UserServiceImpl2 implements UserService

@Autowired
private UserService userService;

根据上面的步骤,可以很容易判断出,直接这么使用是会报错的。
原因:首先通过byType注入,判断UserService类型有两个实现,无法确定具体是哪一个,于是通过byName方式,这里的变量名userService也无法匹配IOC容器中id(此处指的userServiceImpl1和userServiceImpl2),于是报错。
(注意:通过注解注入到IOC容器的id值默认是其类名首字母小写,比如上面的UserServiceImpl1和UserServiceImpl2类bean的id默认为userServiceImpl1和userServiceImpl2)

解决方案:

// 方式一:改变变量名
//将原来的userservice改名为userServiceImpl1,这样就能匹配到对应的唯一bean了
@Autowired
private UserService userServiceImpl1;

// 方式二:配合@Qualifier注解来显式指定name值,这样就能匹配到对应的唯一bean了
@Autowired
@Qualifier(value = "userServiceImpl2")
private UserService userService;

// 方式三:配合@Primary注解来指定自动装配哪一个bean
//加上@Primary,匹配bean时,该bean就会被优先选中。
@Service
@Primary
public class UserServiceImpl1 implements UserService

三、总结
1、@Resource与@Autowired对比

 

2、@Autowired装配流程

 

3、@Resource装配流程