【Spring】IOC/DI中常用的注解@Order与@DependsOn

目录

1、@Order 注解改变Bean自动注入的顺序

1.1、了解@SpringBootTest注解

1.2、@Order 注解改变Bean自动注入的顺序

2、@DependsOn 改变Bean的创建顺序

1、@Order 注解改变Bean自动注入的顺序

        在sping中,通过IOC(控制反转)和DI(依赖注入)这种机制,可以将对象的依赖注入到该对象中,而不是在对象内部直接创建依赖。以达到降低耦合度,提高代码的可维护性和灵活性的目的。

1.1、了解@SpringBootTest注解

@SpringBootTest(classes = 配置类名称.class)

基本等同于启动了整个服务,此时便可以开始功能测试。

        当@SpringBootTest没有指定配置类的时候,默认是把@SpringBootApplication注解下的类作为配置类,然后就会去扫描这个默认配置类所在的包,原因如下图所示

        这里例子里@SpringBootApplication注解下的类所在包为:com.lt,要扫描这个包,把这个包下配置的bean加载到spring容器中去,这些bean才会生效。

(1)如果注解@SpringBootTest(classes = 配置类名称.class)中指定了默认项目配置类,则该测试类可以放在test.java下任何包中,比如:

        图中的测试类(C3IocApplicationTests)的注解@SpringBootTest指定了C3IocApplication(默认项目配置类)为配置类,这时候测试类(C3IocApplicationTests)就可以放在test.java下任何包中

(2)如果注解@SpringBootTest没有配置里面的参数classes = C3IocApplication(默认项目配置类),则需要确保test.java下的测试类所在的包与默认项目配置类所在的包一致,即在test.java下也需要创建com.lt包,并将测试类放在该包下,比如:

        图中的测试类(C3IocApplicationTests)的注解@SpringBootTest没有配置里面的参数classes = C3IocApplication(默认项目配置类),所以这里test.java下的测试类(C3IocApplicationTests)必须与默认配置类(C3IocApplication)所在的包(com.lt)一致,都是在com.lt这个包下

1.2、@Order 注解改变Bean自动注入的顺序

        注解@Order或者接口Ordered的作用是定义Spring IOC容器中Bean的执行顺序的优先级,而不是定义Bean的加载顺序,Bean的加载顺序不受@Order或Ordered接口的影响。所以这里说改变Bean的自动注入的顺序就是改变Bean的执行顺序。

相关代码

//接口
public interface I {
}


//接口I的实现类A
public class A implements I{
    public A(){
        System.out.println("A");
    }
}


//接口I的实现类A
public class B implements I{
    public B(){
        System.out.println("B");
    }
}


//测试类TestOrder
//@SpringBootTest(classes = 启动类名称.class),这里配置了TestOrder.class为项目启动类
@SpringBootTest(classes = TestOrder.class)
public class TestOrder {

    @Bean
    public A a(){
        return new A();
    }

    @Bean
    public B b(){
        return new B();
    }

    @Test
    public void test(@Autowired List<I> i){
        //这里不用List集合的话就只能获取一个I的bean,
        //但是I是有两个实现类的bean,这时候它不知道注入哪一个,就会报错,
        //使用了List集合的话,就会把I的两个实现类的bean都注入到List集合中
        System.out.println(i);
        //没有使用@Order注解时的打印结果为:[com.lt.order.A@4760f169, com.lt.order.B@261ea657]
        //这时候是A在前面,B在后面
    }

}

        在测试类中,用@Autowired注入 I 的bean时,如果不用List集合的话就只能获取一个 I 的bean,但是 I 是有两个实现类的bean,这时候它不知道注入哪一个,就会报错,使用了List集合的话,就会把 I 的两个实现类的bean都注入到List集合中,并且这些bean在List集合中是有顺序的,如果这时候我们想哪个bean排在前面(先执行),就可以通过@Order去改变他的自动装配顺序,谁@Order里面的值小谁排在前面

示例:

用法一,直接加注解,@Order注解中的属性值越小就排的越前

@SpringBootTest(classes = TestOrder.class)
public class TestOrder {
    @Bean
    @Order(1)
    public A a(){
        return new A();
    }

    @Bean
    @Order(0) // 谁小谁在前面
    public B b(){
        return new B();
    }

    @Test
    public void test(@Autowired List<I> i){
        System.out.println(i);
        //使用@Order注解后的打印结果为:[com.lt.order.B@261ea657, com.lt.order.A@4760f169]
        //这时候变成了B在前面,A在后面
    }
}

用法二,实现Ordered接口,重写接口中的getOrder()方法,这个方法的返回值越小,实现类作为bean在List数组中就排的越前面。这下面代码的结果和上面直接加注解的结果一样

public class A implements I, Ordered {
    public A(){
        System.out.println("A");
    }

    @Override
    public int getOrder() {
        return 1;
    }
}


public class B implements I, Ordered {
    public B(){
        System.out.println("B");
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

2、@DependsOn 改变Bean的创建顺序

        @DependsOn注解可以定义在类和方法上,意思是我这个组件要依赖于另一个组件,也就是说被依赖的组件会比该组件先注册到IOC容器中。

使用场景:

        比如我现在有A类和B类,A类是数据库查询,B类是数据库连接,在javaconfig(配置类)中使用@Bean注解把这两个类配置成bean时,可以通过把B类配置成bean的语句写在A类配置成bean的语句前面,来实现先连接数据再查询数据库,但如果配置bean的方式用的是@Component及其衍生注解时,就不好控制bean的创建顺序了,这时候就可以用@DependsOn来改变Bean的创建顺序。

        需要用到观察者模式的情况下通常都需要用到该注解,观察者模式(详细可查看相关文章)有三要输,观察者、事件源、事件,机制是观察者会监听数据源的某些时间,当事件源触发该事件后,观察者就会知道进行相应措施。

        比如老师是观察者,学生是事件源,学生迟到是事件,老师观察学生是否迟到,每当学生迟到,老师就会发现,并处罚该学生。

        这类场景一般需要观察者要比事件源先创建,才能不遗漏事件源触发的每一个事件,要是事件源先创建,可能会在观察者创建前就触发了事件而观察者无法知道。

        比如上述例子,八点算迟到,但是老师自己都八点半才到学校,所以就无法知道八点到八点半之间迟到的学生。

@DependsOn注解可以作用在方法和类上。

(1)当@DependsOn注解作用在类上时

当作用在类上时,通常会与@Component及其衍生注解等注解配合使用。

示例:

代码:还没使用@DependsOn注解

//事件源EventSource,在com.lt.dependsOn包下
@Component
public class EventSource {
    public EventSource(){
        //当调用这个无参构造函数创造bean时,就会执行这条打印语句
        System.out.println("事件源创建");
    }
}


//监听类EventTListener,在com.lt.dependsOn包下
@Component
public class EventTListener {
    public EventTListener(){
        //当调用这个无参构造函数创造bean时,就会执行这条打印语句
        System.out.println("监听器创建");
    }
}


//测试类TestDepends,在com.lt.dependsOn包下
@ComponentScan("com.lt.dependsOn")  //这里要指定扫描"com.lt.dependsOn"这个包,因为这时候用的是@Component来配置bean
@SpringBootTest(classes = TestDepends.class)
public class TestDepends {
    @Test
    public void test(){
    }
}

还没使用@DependsOn注解的运行结果

因为spring默认扫描包时会根据文件在文件夹的位置先后顺序扫描加载,而EventSource 文件位置在EventTListener前面,所以会先加载EventSource 事件源组件。但这就使得两个类的依赖关系不符合逻辑。

使用@DependsOn注解:

//事件源
@Component
@DependsOn(value = {"eventTListener"})
public class EventSource {
    public EventSource(){
        //当调用这个无参构造函数创造bean时,就会执行这条打印语句
        System.out.println("事件源创建");
    }
}

使用@DependsOn注解的运行结果:

这时候就是监听器先创建了。注意:@DependsOn中value属性的bean id必须存在,不然会报错。

(2)当@DependsOn注解作用在方法上时

当作用在方法上时,通常会与@Bean注解配合使用。

要把EventSource和EventTListener类上的注解去掉,再使用下面的代码,因为下面是使用@Bean注解来配置bean的方式

测试类TestDepends代码:

//测试类
@SpringBootTest(classes = TestDepends.class)
public class TestDepends {

    @Bean
    @DependsOn(value = {"eventListener"})
    public EventSource eventSource(){
        return new EventSource();
    }

    @Bean
    public EventTListener eventListener(){
        return new EventTListener();
    }

    @Test
    public void test(){

    }
}

如果不加@DependsOn注解的话,就会先创建事件源,如果加了(如上代码),就会先创建监听器(如下图)

推荐: 
【Spring】依赖注入(DI)时常用的注解@Autowired和@Value-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/m0_65277261/article/details/137784706?spm=1001.2014.3001.5501

【Java网络编程】TCP通信(Socket 与 ServerSocket)和UDP通信的三种数据传输方式-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/m0_65277261/article/details/137926277?spm=1001.2014.3001.5501【Spring】使用@Bean和@Import注解配置Bean,与Bean的实例化_import和bean-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/m0_65277261/article/details/137257177?spm=1001.2014.3001.5501

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/571190.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【分治】Leetcode 数组中的第K个最大元素

题目讲解 数组中的第K个最大元素 算法讲解 堆排序&#xff1a;1. 寻找最后一个节点的父亲&#xff0c;依次向上遍历&#xff0c;完成小堆的建立&#xff1b;2. 从最后一个元素开始&#xff0c;和堆顶的数据做交换&#xff0c;此时最小的数据在对后面&#xff0c;然后对剩下的…

虚幻引擎5 Gameplay框架(一)

GamePlay概论与打包和批处理脚本 GamePlay简介与创建项目 GamePlay框架&#xff1a;用于设计游戏规则&#xff0c;组织和管理游戏核心逻辑、规则以及交互的一套结构化体系。 Default Pawn Class&#xff1a;定义角色行为逻辑&#xff0c;接收玩家控制器的输入&#xff0c;一般…

Linux 基础IO(2)磁盘文件

文章目录 1.磁盘文件2.文件系统3.软硬链接1.软链接2.硬链接 4.动静态库1.静态库2.动态库 1.磁盘文件 扇区&#xff1a;整个盘片分成不同的区块&#xff0c;每一个区块就是一个扇区。 扇区是磁盘IO的基本单位&#xff0c;一般为512Byte或4KB,一般磁盘都是512Byte磁道&#xff1a…

Mysql 查询表参考

基本操作 数据库和表的基础操作_数据库和表的基本操作-CSDN博客文章浏览阅读222次。数据库基础知识_数据库和表的基本操作https://blog.csdn.net/weixin_67573348/article/details/126946843 单表 语法分析&#xff1a;MySQL 单表查询 语法分析_adn查询-CSDN博客文章浏览阅读…

CTFHub(web sql注入)(三)

MYSQL 手工注入 1.判断字段数 输入1 输入2 输入3 得知字段有两个 2.判断注入类型 1 and 1 1 1 and 12 回显错误&#xff0c;说明存在sql注入 3.查看数据库内容 知道字段数量为2后&#xff0c;可以查看数据库位置 1 union select 1,2 使用union select 1,2查看未发现数…

【2023】springboot通过阿里云oss进行文件单个批量文件上传下载

SpringBoot整合阿里OSS实现上传下载 目录&#x1f4bb; 前言一、介绍二、阿里云添加oss1、进入oss目录2、创建bucket3、测试上传下载4、创建AccessKey管理账号 三、依赖以及配置1、依赖2、yml3、Config类4、OSSUtil 工具类 四、controller五、测试1、测试上传2、测试删除 前言 …

【调制】π/4-DQPSK信号模型及其相关特性分析 【附MATLAB代码】

MATLAB代码 % pi/4-DQPSK modulation %输入一串数&#xff0c;输出经过差分并映射的I、Q两路数据 ​ function [I,Q]pi4_dqpskmod(data) ​ nlength(data)./2; data1data.*2-1; ​ Idatazeros(1,n); Qdatazeros(1,n); ​ ​ Idatadata1(1,1:2:2*n); %串并变换 Qdatadata1(…

用户中心 -- 代码理解

一、删除表 & if 删除表 1.1 DROP TABLE IF EXISTS user 和 DROP TABLE user 网址&#xff1a; 用户管理第2节课 -- idea 2023.2 创建表--【本人】-CSDN博客 二、 代码 2.1 清空表中数据 的 命令 【truncate 清空】 网址&#xff1a; 用户管理第2节课 -- idea 2…

卡尔曼滤波器(二):Simulink卡尔曼滤波器模块使用

观看MATLAB技术讲座笔记&#xff0c;该技术讲座视频来自bilibili账号&#xff1a;MATLAB中国。 本节在Simulink中用卡尔曼滤波器来滤除传感器噪声&#xff0c;准确估算单摆摆角。 一、单摆模型简介 不考虑摩擦时&#xff0c;下图所示的单摆力学平衡方程为&#xff1a; m l 2…

‍ 太空网络攻击

&#x1f9d1;‍&#x1f680; 尤里-加加林成为征服外太空的第一人。他在 1961 年 4 月 12 日的飞行有力地推动了全世界的科技发展。 有趣的事实是&#xff1a;苏联所有首次太空发射&#xff08;包括加加林的飞行&#xff09;的弹道计算都是在苏联第一个计算机中心的电子计算机…

从数据库中到处所有表的列、注释、类型、是否必填等信息

从数据库中到处所有中文表名、英文表名、所有列、注释、类型、长度、是否必填等信息&#xff0c;效果如下&#xff1a; 要实现上面的表格可以直接用SQL实现&#xff0c;实现SQL如下&#xff1a; #查询SQL select* FROMinformation_schema.COLUMNS as columns left join (sele…

(七)Idea编辑器集成Tomcat

1. 点击桌面上Idea快捷方式打开Idea编辑器&#xff0c;假如没有创建项目的话打开Idea编辑器后的界面展示如下图所示 2. 点击界面左侧菜单中的自定义 3. 然后点击界面中的“所有设置...”,然后点击“构建、执行、部署”&#xff0c;选择其中的“应用程序服务器” 4. 点击“”按钮…

LeetCode 1052. 爱生气的书店老板

题目链接 https://leetcode.cn/problems/grumpy-bookstore-owner/description/?envTypedaily-question&envId2024-04-23 先把最初的满意人数累加算出来&#xff0c;然后使用滑动窗口来模拟连续 minutes分钟不生气&#xff0c;计算不生气minutes分钟最大的满意数 class S…

【智能算法】吉萨金子塔建造算法(GPC)原理及实现

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.结果展示4.参考文献 1.背景 2021年&#xff0c;S Harifi等人受到观古代遗迹构造启发&#xff0c;提出了吉萨金子塔建造算法&#xff08;Giza Pyramids Construction, GPC&#xff09;。 2.算法原理 2.1算法思想 GPC模拟了古埃…

LeetCode:2385. 感染二叉树需要的总时间(DFS Java)

目录 2385. 感染二叉树需要的总时间 题目描述&#xff1a; 实现代码与解析&#xff1a; DFS 原理思路&#xff1a; 2385. 感染二叉树需要的总时间 题目描述&#xff1a; 给你一棵二叉树的根节点 root &#xff0c;二叉树中节点的值 互不相同 。另给你一个整数 start 。在第…

文本语音互相转换系统设计

title: 文本语音互相转换系统设计 date: 2024/4/24 21:26:15 updated: 2024/4/24 21:26:15 tags: 需求分析模块化设计性能优化系统安全智能化跨平台区块链 第一部分&#xff1a;导论 第一章&#xff1a;背景与意义 文本语音互相转换系统的定义与作用 文本语音互相转换系统是…

CTFshow-PWN-栈溢出(pwn43)

32位的 system(); 但是好像没"/bin/sh" 上面的办法不行了&#xff0c;想想办法 检查&#xff1a;32 位程序 ida 分析&#xff1a; 跟进 ctfshow 函数 定义了一个长度为 104 的字符数组 s&#xff0c;gets() 函数被用来从标准输入&#xff08;键盘&#xff09;中读取…

CU-Mamba:具有通道学习功能的选择性状态空间模型用于图像恢复

CU-Mamba&#xff1a;具有通道学习功能的选择性状态空间模型用于图像恢复 摘要IntroductionRelated WorkMethod CU-Mamba: Selective State Space Models with Channel Learning for Image Restoration 摘要 重建退化图像是图像处理中的关键任务。尽管基于卷积神经网络&#x…

【人工智能基础】人工神经网络

一、人工神经网络的三要素 人工神经元数理模型 MP模型是世界上第一个神经计算模型&#xff0c;为神经网络理论提供了基础 MP模型功能 对树突输入u的线性加权求和对净输入的非线性转换\ 作用函数的功能作用函数的功能 MP神经元模型的作用函数是单位阶跃函数。当x≥0时f(x)…

JTS:Java Topology Suit

接口文档:org.locationtech.jts:jts-core 1.19.0 API。 开发文档:JTS | Documentation。 概述 JTS提供了平面线性几何(planar and linear geometry)与相关的基础几何处理函数(a set of fundamental geometric functions.)。 JTS遵循OGC发布的简单几何规范(Simple Featu…