IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> @Autowired和@Resource的注入过程/区别 -> 正文阅读

[Java知识库]@Autowired和@Resource的注入过程/区别

目录

1 前言

2 demo演示

2.1 @Autowired注解

2.1.1 ByType>>>ByName

2.2.2 ByType>>>autowireCandidate>>>ByName

2.2.2 ByType>>>autowireCandidate>>>Qualifier>>>ByName

2.2.4?ByType>>>autowireCandidate>>>Qualifier>>>Primary>>>ByName

2.2?@Resource


1 前言

????????@Autowired注解和@Resource注解都是我们在开发中常用的注解,但是大家可以发现,有些人自动注入的时候用@Autowired,有的人用了@Resource,那么它们有什么区别呢?那么什么时候用@Autowired什么时候用@Resource呢?

首先先说明下,@Autowired注解默认是按照type注入的,而@Resource注解默认是按照name注入的。那么我们就通过小demo来演示下。

2 demo演示

2.1 @Autowired注解

2.1.1 ByType>>>ByName

配置两个单例bean:OrderServcice和UserServcice,在UserService中注入OrderServcie

单例bean:OrderService

@Component
public class OrderService {
}

单例bean:UserService

@Component
public class UserService {

    @Autowired
    private OrderService orderService;

}

再配置两个orderService类型的bean:orderService1和orderService2

@ComponentScan("com.liubujun")
public class AppConfig {

    @Bean
    public OrderService orderService1(){
        return new OrderService();
    }

    @Bean
    public OrderService orderService2(){
        return new OrderService();
    }


}

测试类:

    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
        System.out.println(applicationContext.getBean("orderService"));

    }

测试结果:

测试显示可以正常注入成功。这个时候有人可能就要问了。这说与不说有什么区别吗?我们都知道@?Autowired注解是先根据类型找,然后在根据属性名字找啊,这里先根据类型找找到了OrderService类型的有3个(OrderService,OrderService1,OrderService2),然后在根据名字找自己定义的orderService从而找到了这不是很正常。其实这中间的过程并没有那么简单。其实中间还会去判断是不是自动填充的候选者(autowireCandidate())默认是true.

2.2.2 ByType>>>autowireCandidate>>>ByName

之前说了@Autowired注解其实属性注入时并不是直接进行type完成之后,就直接根据name进行判断,中间还要判断是否是自动填充的候选者,这个属性有默认值,默认值是true。

boolean autowireCandidate() default true;

进行测试,我们将之前的普通bean进行修改,如下:

@ComponentScan("com.liubujun")
public class AppConfig {

    @Bean(autowireCandidate = false)
    public OrderService orderService1(){
        return new OrderService();
    }

    @Bean
    public OrderService orderService2(){
        return new OrderService();
    }


}

属性注入改成注入orderService1如下:

@Component
public class UserService {

    @Autowired
    private OrderService orderService1;

}

再次进行测试结果:报错结果如下

Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userService': Unsatisfied dependency expressed through field 'orderService1'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.liubujun.service.OrderService' available: expected single matching bean but found 2: orderService,orderService2

原因解释如下:

属性注入时先根据type去找,找到了OrderService类型的有3个(OrderService,OrderService1,OrderService2)。然后根据是否是自动填充的候选者进行筛选,发现nam为OrderService1上的属性autowireCandidatefalse,那么就剩下两个OrderService类型的有2个(OrderService,OrderService2),再根据name去匹配,发现没有name为OrderService1的属性,于是就报错了。

2.2.2 ByType>>>autowireCandidate>>>Qualifier>>>ByName

除此之外,属性注入的过程还会有一个分组的概念,可以经过Qualifier进行分组。例如:

对orderService1进行分组xxx的分组,然后注入的时候也进行分组,这个时候即使属性名称不一样也不会进行报错,修改代码如下:

@ComponentScan("com.liubujun")
public class AppConfig {

    @Bean
    @Qualifier("xxx")
    public OrderService orderService1(){
        return new OrderService();
    }

    @Bean
    public OrderService orderService2(){
        return new OrderService();
    }


}
@Component
public class UserService {

    @Autowired
    @Qualifier("xxx")
    private OrderService orderService111;

}

启动测试类:发现不会报错

?分析如下:

属性注入时先根据type去找,找到了OrderService类型的有3个(OrderService,OrderService1,OrderService2)。然后根据是否是自动填充的候选者进行筛选,发现都是true(默认都是true)再看是否有进行Qualifier分组,有的话就根据分组name名称去找。找到了xxx,然后就正常输出。

2.2.4?ByType>>>autowireCandidate>>>Qualifier>>>Primary>>>ByName

以上经过筛选之后,可能一个类型下还有多个bean,那么通过加一个@Primary注解,让该bean成为主bean。那么即使注入的名称不一样也不会报错。代码修改如下:

@ComponentScan("com.liubujun")
public class AppConfig {

    @Bean
    @Primary
    public OrderService orderService1(){
        return new OrderService();
    }

    @Bean
    public OrderService orderService2(){
        return new OrderService();
    }


}
@Component
public class UserService {

    @Autowired
    private OrderService orderService111;

}

测试启动类正常输出:

?原因分析:属性注入时先根据type去找,找到了OrderService类型的有3个(OrderService,OrderService1,OrderService2)。然后根据是否是自动填充的候选者进行筛选,发现都是true(默认都是true)再看是否有进行Qualifier分组,发现没有再看bean上面是否有Primary注解如果有,那么它就是主bean,就会将该bean赋值给需要注入的bean。

除此之外,也会通过其它的方式获取优先级最高的bean。

总结@Autowired获取bean方式如下图:

2.2?@Resource

????????@Resource会先根据name进行匹配,然后根据type去进行匹配,但是如果该注解上指定了name的话,没有根据name找到就会报错。修改代码如下:

@Component
public class UserService {

    @Resource(name = "123")
    private OrderService orderService111;

}

启动测试类,报错信息如下:

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userService': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named '123' available

如果指定name值,根据name去找找不到的话,就不会根据type去找了。

但如果没有指定name的话,根据name找不到,就会根据type去找了。

修改如下:

@Component
public class UserService {

    @Resource
    private OrderService orderService111;

}

启动测试类,依然报错。报错信息如下:

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userService': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.liubujun.service.OrderService' available: expected single matching bean but found 3: orderService,orderService1,orderService2

原因如下:因为根据name去找的时候,发现没有name为orderServcice111的 类型,然后根据类型去找,但是这个时候发现却找到了3个。所以报错了,此时,将那两个普通bean注释掉就可以正常输出了。修改代码如下:

@ComponentScan("com.liubujun")
public class AppConfig {

//    @Bean
//    public OrderService orderService1(){
//        return new OrderService();
//    }
//
//    @Bean
//    public OrderService orderService2(){
//        return new OrderService();
//    }


}

测试类启动,正常输出:

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-03-31 23:49:43  更:2022-03-31 23:53:22 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 6:59:13-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码