5. @Autowired与@Resource的区别

在上一节我们使用Autowired进行了bean的装配,@Autowired与@Resource都可以用来装配bean,但它们之前还是有一些区别,它们的区别具体体现为以下几点:

  • 来源不同
  • 对Constructor注入的支持不同
  • 查找顺序不同
  • 支持参数不同

1. 来源不同

@Resource位于包javax.annotation,是JDK原生的注解;

@Autowired位于包org.springframework.beans.factory.annotation
,是Spring2.5 之后引入的注解。

2. 对Constructor注入的支持不同

由于构造方法在对象创建的时候调用,执行的时期较早,由于jdk将@Resource的执行时期设计晚于构造方法调用的时期,因此在构造方法上使用@Resource注解编译器会报错:

image.png

3. 查找顺序不同

3.1 Bean在Spring中的存储方式

Bean在Spring中的存储方式是类似于Java中的HashMap的。

一个Bean对象有它的NameType,分别对应着xml文件中配置的Bean的idclass

也就是说通过同一个类可以创建两个id不同的Bean对象:

<bean id="user1" class="UserBean"></bean>
<bean id="user2" class="UserBean"></bean>

通过Java的数据结构HashMap<key, value>,我们可以通过key(键)找到对应的value(值),而Bean的Name+Type,就对应着key,而Bean对象就对应着value

3.2 @Autowired查找顺序

下面的代码中,DemoDao对应着TypedemoDao对应着Name

@Autowired
private DemoDao demoDao;

@Autowired是先通过Type查找,如果一个Type对应多个Bean,它才会去通过Name查找,如果找不到唯一的Name,那么就会抛出异常。

实验验证:

第一次,只有DemoDaoImpl实现DemoDao接口,UserService的代码如下,只有Bean的Type能匹配上,而Name无法匹配上:

@Service
public class UserService {
    @Autowired
    private DemoDao demoDao;

    public void doService() {
        demoDao.selectAll();
        System.out.println("Do User Service");
    }
}

成功找到Bean并运行:

select * from demo
Do User Service
Do User Controller.

第二次,我让DemoDaoImplUserDaoImpl都实现DemoDao接口:

@Repository
public class DemoDaoImpl implements DemoDao {

    @Override
    public void selectAll() {
        System.out.println("select * from demo");
    }
}
@Repository
public class UserDaoImpl implements DemoDao {
    @Override
    public void selectAll() {
        System.out.println("select * from user");
    }
}

运行程序发现报了一个没有唯一定义的Bean的异常:

NoUniqueBeanDefinitionException: No qualifying bean of type 'com.chenshu.dao.DemoDao' available: 

第三次,我同样让DemoDaoImplUserDaoImpl都实现DemoDao接口,并且让UserService中的NameDemoDaoImpl匹配上:

@Service
public class UserService {
    @Autowired
    private DemoDao demoDaoImpl;

    public void doService() {
        demoDaoImpl.selectAll();
        System.out.println("Do User Service");
    }
}

这次又能正常注入Bean,并成功调用Bean的方法:

select * from demo
Do User Service
Do User Controller.

上面的结论足以验证@Autowired的查找顺序是先通过Type查找再通过Name查找。

3.3 @Resource查找顺序

这里我直接给出结论:@Resource 是先根据名称查找,如果(根据名称)查找不到,再根据类型进行查找。

4. 支持参数不同

点开@Resource注解并查看它的Structure:
image.png

点开@Autowired注解并查看它的Structure:
image.png

对比二者,@Resource注解提供了更丰富的参数

4.1 引入需求

UserService代码如下:

@Service
public class UserService {
    @Autowired
    private DemoDao demoDao;

    public void doService() {
        demoDao.selectAll();
        System.out.println("Do User Service");
    }
}

此时有UserDaoImplDemoDaoImpl实现DemoDao接口,现在我想在不改变参数名的情况下,解决一个类对应两个Bean对象的问题

4.2 解决方案

方案一:通过@Resource注解

@Resource注解提供了一个name参数,通过该参数可以指定通过该参数的值来查找Bean:

@Service
public class UserService {
    @Resource(name = "userDaoImpl")
    private DemoDao demoDao;

    public void doService() {
        demoDao.selectAll();
        System.out.println("Do User Service");
    }
}

方案二:通过@Autowired注解

虽说@Resource能够通过参数便利地解决问题,但它还是有个硬伤:无法实现构造器注入。

@Autowired没有提供相应的参数实现该需求,但是我们可以通过额外的@Qualifier注解来实现:

@Service
public class UserService {
    @Autowired
    @Qualifier(value = "userDaoImpl")
    private DemoDao demoDao;

    public void doService() {
        demoDao.selectAll();
        System.out.println("Do User Service");
    }
}
```在上一节我们使用Autowired进行了bean的装配,@Autowired@Resource都可以用来装配bean,但它们之前还是有一些区别,它们的区别具体体现为以下几点:
- 来源不同
-Constructor注入的支持不同
- 查找顺序不同
- 支持参数不同


# 1. 来源不同
`@Resource`位于包`javax.annotation`,是JDK原生的注解;

而`@Autowired`位于包`org.springframework.beans.factory.annotation`
,是Spring2.5 之后引入的注解。
# 2.Constructor注入的支持不同
由于构造方法在对象创建的时候调用,执行的时期较早,由于jdk将@Resource的执行时期设计晚于构造方法调用的时期,因此在构造方法上使用@Resource注解编译器会报错:

![image.png](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a2c31913d1d74067862b301fca4dbd44~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=382&h=87&s=11624&e=png&b=1c1c1f)
# 3. 查找顺序不同
## 3.1 BeanSpring中的存储方式
BeanSpring中的存储方式是类似于Java中的`HashMap`的。

一个Bean对象有它的`Name`和`Type`,分别对应着xml文件中配置的Bean的`id`和`class`

也就是说通过同一个类可以创建两个`id`不同的Bean对象:
```xml
<bean id="user1" class="UserBean"></bean>
<bean id="user2" class="UserBean"></bean>

通过Java的数据结构HashMap<key, value>,我们可以通过key(键)找到对应的value(值),而Bean的Name+Type,就对应着key,而Bean对象就对应着value

3.2 @Autowired查找顺序

下面的代码中,DemoDao对应着TypedemoDao对应着Name

@Autowired
private DemoDao demoDao;

@Autowired是先通过Type查找,如果一个Type对应多个Bean,它才会去通过Name查找,如果找不到唯一的Name,那么就会抛出异常。

实验验证:

第一次,只有DemoDaoImpl实现DemoDao接口,UserService的代码如下,只有Bean的Type能匹配上,而Name无法匹配上:

@Service
public class UserService {
    @Autowired
    private DemoDao demoDao;

    public void doService() {
        demoDao.selectAll();
        System.out.println("Do User Service");
    }
}

成功找到Bean并运行:

select * from demo
Do User Service
Do User Controller.

第二次,我让DemoDaoImplUserDaoImpl都实现DemoDao接口:

@Repository
public class DemoDaoImpl implements DemoDao {

    @Override
    public void selectAll() {
        System.out.println("select * from demo");
    }
}
@Repository
public class UserDaoImpl implements DemoDao {
    @Override
    public void selectAll() {
        System.out.println("select * from user");
    }
}

运行程序发现报了一个没有唯一定义的Bean的异常:

NoUniqueBeanDefinitionException: No qualifying bean of type 'com.chenshu.dao.DemoDao' available: 

第三次,我同样让DemoDaoImplUserDaoImpl都实现DemoDao接口,并且让UserService中的NameDemoDaoImpl匹配上:

@Service
public class UserService {
    @Autowired
    private DemoDao demoDaoImpl;

    public void doService() {
        demoDaoImpl.selectAll();
        System.out.println("Do User Service");
    }
}

这次又能正常注入Bean,并成功调用Bean的方法:

select * from demo
Do User Service
Do User Controller.

上面的结论足以验证@Autowired的查找顺序是先通过Type查找再通过Name查找。

3.3 @Resource查找顺序

这里我直接给出结论:@Resource 是先根据名称查找,如果(根据名称)查找不到,再根据类型进行查找。

4. 支持参数不同

点开@Resource注解并查看它的Structure:
image.png

点开@Autowired注解并查看它的Structure:
image.png

对比二者,@Resource注解提供了更丰富的参数

4.1 引入需求

UserService代码如下:

@Service
public class UserService {
    @Autowired
    private DemoDao demoDao;

    public void doService() {
        demoDao.selectAll();
        System.out.println("Do User Service");
    }
}

此时有UserDaoImplDemoDaoImpl实现DemoDao接口,现在我想在不改变参数名的情况下,解决一个类对应两个Bean对象的问题

4.2 解决方案

方案一:通过@Resource注解

@Resource注解提供了一个name参数,通过该参数可以指定通过该参数的值来查找Bean:

@Service
public class UserService {
    @Resource(name = "userDaoImpl")
    private DemoDao demoDao;

    public void doService() {
        demoDao.selectAll();
        System.out.println("Do User Service");
    }
}

方案二:通过@Autowired注解

虽说@Resource能够通过参数便利地解决问题,但它还是有个硬伤:无法实现构造器注入。

@Autowired没有提供相应的参数实现该需求,但是我们可以通过额外的@Qualifier注解来实现:

@Service
public class UserService {
    @Autowired
    @Qualifier(value = "userDaoImpl")
    private DemoDao demoDao;

    public void doService() {
        demoDao.selectAll();
        System.out.println("Do User Service");
    }
}

相关推荐

  1. @Autowired@Resource区别

    2024-04-13 05:06:01       20 阅读
  2. @Autoware和@Resource区别

    2024-04-13 05:06:01       30 阅读
  3. Spring面试整理-AutowiredResource关键字区别

    2024-04-13 05:06:01       38 阅读
  4. 深入理解@Resource@Autowired:用法区别解析

    2024-04-13 05:06:01       37 阅读
  5. Spring中@Resource/@Autowired/@Primary/@Qualifier

    2024-04-13 05:06:01       35 阅读
  6. 【SpringBoot】@Autowired 和 @Resource 使用

    2024-04-13 05:06:01       26 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-13 05:06:01       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-13 05:06:01       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-13 05:06:01       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-13 05:06:01       20 阅读

热门阅读

  1. Kafka

    Kafka

    2024-04-13 05:06:01      11 阅读
  2. props组件传值(子串子)

    2024-04-13 05:06:01       13 阅读
  3. postgresql命令

    2024-04-13 05:06:01       15 阅读
  4. SQL Server详细使用教程

    2024-04-13 05:06:01       15 阅读
  5. 干货分享|TensorFlow构建神经网络

    2024-04-13 05:06:01       15 阅读
  6. hive sql一直跑到reduce=100%,然后挂掉重新跑

    2024-04-13 05:06:01       41 阅读
  7. 【CMake】CMake打包Dll

    2024-04-13 05:06:01       19 阅读
  8. python内置函数compile(),complex()详解

    2024-04-13 05:06:01       16 阅读
  9. AWS被误扣费了,怎么解决?

    2024-04-13 05:06:01       14 阅读