@Autowired和@Resource的区别

@Autowired@Resource都是Spring项目中用于进行依赖注入的注解,它们的区别是什么?

注解来源不一样

@Resource是JavaEE提供的,在javax.annotation包中去定义的。
@Autowired是Spring框架提供的,专门用于自动装配 Spring 容器中的 Bean

装配方式不一样

@Resource

@Resource默认根据名称去寻找容器中的对象,如果名称不存在,才根据类型去寻找。

假如我有一个Jiejie和JiejieSon的对象,它们都实现了IJiejie接口
在这里插入图片描述
IJiejie接口

public interface IJiejie {
}

Jiejie类

@Service
public class Jiejie  implements IJiejie{
}

JiejieSon类

@Service
public class JiejieSon implements IJiejie{
}

接着我定义了一个TestService类来测试
TestService

@Component
public class TestService implements CommandLineRunner {
    @Resource
    private Jiejie jiejieSon;

    @Override
    public void run(String... args) throws Exception {
        System.out.println(jiejieSon);
    }
}

我的类型是Jiejie,然后名称是jiejieSon,由于是@Resource注解,然后它是默认根据名称去寻找的,jiejieSon是能找到的,即JiejieSon,然而我却用Jiejie去接收,类型不一样,运行之后会报错,启动后果然出现了错误。

Caused by: org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named ‘jiejieSon’ is expected to be of type ‘com.itheima.pojo.Jiejie’ but was actually of type ‘com.itheima.pojo.JiejieSon’
引起的原因:org.springframework.beans.factory.BeanNotOfRequiredTypeException:名为 ‘jiejieSon’ 的 Bean 期望为 ‘com.itheima.pojo.Jiejie’ 类型,但实际为 ‘com.itheima.pojo.JiejieSon’ 类型。

如果名称找不到,会根据类型去寻找,比如我将jiejieSon改为jiejieSon1,因为JiejieSon1对象是不存在的,这个时候会根据类型寻找,且不会报错

@Component
public class TestService implements CommandLineRunner {
    @Resource
    private Jiejie jiejieSon1;

    @Override
    public void run(String... args) throws Exception {
        System.out.println(jiejieSon1);
    }
}

控制台输出为com.itheima.pojo.Jiejie@15b0d4d4,说明名称找不到,使用了类型去寻找。

@Autowired

@Autowired默认会根据类型去寻找,如果类型有多个实现的时候,再根据名称去查找。

还是之前的例子,但我把注解换成了@Autowired

@Component
public class TestService implements CommandLineRunner {
    @Autowired
    private Jiejie jiejieSon;

    @Override
    public void run(String... args) throws Exception {
        System.out.println(jiejieSon);
    }
}

这份代码中在@Resource的实验中是报错的,但在这里是正常运行,启动后控制台输出
com.itheima.pojo.Jiejie@67d90a8b,因为默认根据类型寻找。

假如我有多个实现的时候,这个时候根据名称寻找。
前面有提到过,我定义了一个IJiejie的接口,而JiejieJiejieSon都实现了它。

@Component
public class TestService implements CommandLineRunner {
    @Autowired
    private IJiejie jiejieSon;

    @Override
    public void run(String... args) throws Exception {
        System.out.println(jiejieSon);
    }
}

上面这份代码中,因为IJiejie有多个实现,根据名称寻找,jiejieSon通过名称寻找则会找到JiejieSon这个对象,控制台输出com.itheima.pojo.JiejieSon@67d90a8b

下面这份代码,我改成了jiejie,根据名称寻找到Jiejie对象,控制台输出com.itheima.pojo.Jiejie@67d90a8b

@Component
public class TestService implements CommandLineRunner {
    @Autowired
    private IJiejie jiejie;

    @Override
    public void run(String... args) throws Exception {
        System.out.println(jiejie);
    }
}

好,那么如果我写的既不是jiejie也不是jiejieSon,而是写成jiejie1,这会出现什么问题,由于根据名称去寻找,它想找的是Jiejie1对象,然而并没有,因此会报错

@Component
public class TestService implements CommandLineRunner {
    @Autowired
    private IJiejie jiejie1;

    @Override
    public void run(String... args) throws Exception {
        System.out.println(jiejie1);
    }
}
***************************
APPLICATION FAILED TO START
***************************

Description:

Field jiejie1 in com.itheima.Serivce.TestService required a single bean, but 2 were found:
	- jiejie: defined in file [D:\IntelliJ IDEA\Project\Project\tlias-management\target\classes\com\itheima\pojo\Jiejie.class]
	- jiejieSon: defined in file [D:\IntelliJ IDEA\Project\Project\tlias-management\target\classes\com\itheima\pojo\JiejieSon.class]

This may be due to missing parameter name information

Action:

Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed

Ensure that your compiler is configured to use the '-parameters' flag.
You may need to update both your build tool settings as well as your IDE.
(See https://github.com/spring-projects/spring-framework/wiki/Upgrading-to-Spring-Framework-6.x#parameter-name-retention)

这个报错翻译为:

***************************  
应用程序启动失败  
***************************  

描述:  

com.itheima.Serivce.TestService 中的字段 jiejie1 需要一个单一的 Bean,但找到 2 个:  
	- jiejie:定义在文件 [D:\IntelliJ IDEA\Project\Project\tlias-management\target\classes\com\itheima\pojo\Jiejie.class]  
	- jiejieSon:定义在文件 [D:\IntelliJ IDEA\Project\Project\tlias-management\target\classes\com\itheima\pojo\JiejieSon.class]  

这可能是由于缺少参数名称信息导致的  

操作:  

考虑将其中一个 Bean 标记为 @Primary,更新消费者以接受多个 Bean,或使用 @Qualifier 来识别应该被消费的 Bean  

确保您的编译器配置使用 '-parameters' 标志。  
您可能需要更新构建工具设置以及您的 IDE。  
(请参阅:https://github.com/spring-projects/spring-framework/wiki/Upgrading-to-Spring-Framework-6.x#parameter-name-retention)

要解决这个问题,我们可以配合@Qualifier去使用

@Component
public class TestService implements CommandLineRunner {
    @Autowired
    @Qualifier("jiejieSon")
    private IJiejie jiejie1;

    @Override
    public void run(String... args) throws Exception {
        System.out.println(jiejie1);
    }
}

控制台输出com.itheima.pojo.JiejieSon@73fdecc0

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值