SpringBoot原理(@Conditional)—三种自动配置方法、步骤详解

news2024/11/19 14:40:47

简介:我们一直在说基于SpringBoot开发简单、快捷,但是总是不太清楚为什么会有这样的便利,对于开发人员来说我们不仅要知其然,还要知其所以然,这篇文章就是说明SpringBoot的底层原理,让读者对SpringBoot底层的运行机制有深一层的了解。

目录

1、起步依赖

2、自动配置

2.1 自动配置原理

2.2 @Conditional注解

2.3 案例(自定义starter)

3、总结


1、起步依赖

  • SpringBoot 通过提供众多起步依赖降低项目依赖的复杂度。起步依赖本质上是一个Maven项目对象模型(Project Object Model,POM),定义了对其他库的传递依赖,这些东西加在一起即支持某项功能。很多起步依赖的命名都暗示了它们提供的某种或某类功能。

2、自动配置

  • SpringBoot的自动配置就是当spring容器启动后,一些配置类、bean对象就自动存入到了IOC容器中,不需要我们去手动声明,从而简化了开发,省去了繁琐的配置操作。

2.1 自动配置原理

  • 方案一:@ComponentScan 组件扫描
图 2.1-1 添加第三方地址
上图是在当前项目的pom.xml配置文件中添加第三方项目的地址,从而可以在当前项目引用第三方项目资源。
图 2.1-2 @ComponentScan()注解 

上图中的 @ComponentScan()注解定义在当前项目启动类中,当前项目启动时会自动扫描参数中包名的所有bean对象并将其存储到IOC容器中。

优势:能全面的扫描的包内的所有bean对象。

缺点:性能慢,开发中不是所有的bean都需要(主流开发不使用)。

  • 方案二:@import导入。使用@import导入的类会被加载到IOC容器中,导入的形式主要有以下几种:
    • 导入 普通类
    • 导入 配置类
    • 导入 ImportSelector 接口实现类
    • @EnableXxxx注解,封装@import注解
图 2.1-3  添加第三方项目地址
图片中展示的是在本项目的pom.xml文件中添加第三方项目的地址依赖,这样就可以在本项目中使用第三方的资源。(备注:下面几种,第三方bean对象导入IOC容器中,都是在第三方项目的地址已经在pom.xml文件中的基础上
图 2.1-4 import 导入普通类、配置类
上图中是通过@Import() 注解(注解中的参数为被调用第三方资源的类名称),调用第三方项目的资源且将被调用的资源对象存储到IOC容器中。
图 2.1-5 导入 ImportSelector 接口实现类

上图是在被调用第三方项目中创建一个 ImportSelector 接口的实现类  MyImportSelector ,实现类返回值为允许被调用bean对象资源的全类名。

图 2.1-6 导入 ImportSelector 接口实现类

上图是在当前项目启动类中通过 @Import 注解,将第三方项目的接口实现类(图 2.1-5)MyImportSelector导入。

图 2.1-7 使用@EnableXxxx注解
上图是在图2.1-6的基础上,在第三方资源项目中创建 EnableHeaderConfig注解并且使用 @Import()注解引用第三方资源项目的接口实现类  MyImportSelector,这样开发者直接在当前开发项目中直接使用 EnableHeaderConfig注解就可以了。  这也是当前开发工作中的主流方式。

2.2 @Conditional注解

图 2.2-1 使用@Conditional注解
上图是 @Conditional的作用,他是一个父级注解,开发中最主要的就是三个字注解,需要掌握这三个子注解的使用方法。
图 2.2-2 使用@Conditional 相关子注解

上图中在第三方资源项目中的 HeaderConfig类中,使用了三个注解;

  1. @ConditionalOnMissingBean //不存在该类型的bean,才会将该bean加入到IOC容器中 -- 指定类型(value属性) 或 名称(name属性)
  2. @ConditionalOnClass(name = "io.jsonwebtoken.Jwts") //环境中存在指定的这个类,才会将该bean加入IOC容器中
  3. @ConditionalOnProperty() //配置文件中存在指定的属性与值,才会将该bean加入到IOC容器中

开发者可以根据需要,自主在第三方资源项目中选择使用这三个注解中适用的,方便将注解对应的bean对象放进当前引用的第三方资源

2.3 案例(自定义starter)

在实际的开发过程中,经常会定义一些公共组件,提供给各个项目团队使用。而在SpringBoot的项目中,一般会把这些公共组件封装为SpringBoot的starter。

下面是在IDEA项目中创建一个自定义starter依赖,关于操作阿里云OSS的操作工具类。

图 2.3-1 自定义starter
图片中是创建一个阿里云OSS操作工具类的项目依赖步骤,分为依赖管理功能、自动配置功能。
图 2.3-2 创建starter
图 2.3-3 创建autoconfigure模块
上图中是在当前项目中创建autoconfigure模块,并且只保留pom.xml、iml、src文件,其他的删除掉。

之后是在创建的autoconfigure模块中的pom.xml文件中添加阿里云的相关依赖(代码如下)

        <!--web起步依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!--添加阿里云的依赖-->
        <!--阿里云OSS-->
        <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-sdk-oss</artifactId>
            <version>3.15.1</version>
        </dependency>
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.3.1</version>
        </dependency>
        <dependency>
            <groupId>javax.activation</groupId>
            <artifactId>activation</artifactId>
            <version>1.1.1</version>
        </dependency>

只有在autoconfigure模块中的pom.xml文件中添加依赖后,才能编写代码。

  1. 接下来是去创建 AliOSSProperties 类,这是一个属性类,用于记录阿里云的秘钥等数据(代码如下)
    package com.aliyun.oss;
    
    import lombok.Data;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    
    @Data
    @ConfigurationProperties(prefix = "aliyun.oss")
    public class AliOSSProperties {
        private String endpoint;
        private String accessKeyId;
        private String accessKeySecret;
        private String bucketName;
    }
    
  2. 之后是创建阿里云OSS工具类  AliOSSUtils,这个类的功能是将文件上传至阿里云中(代码如下)
    package com.aliyun.oss;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.multipart.MultipartFile;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.UUID;
    
    /**
     * 阿里云 OSS 工具类
     */
    public class AliOSSUtils {
    
    //    @Value("${aliyun.oss.endpoint}")
    //    private String endpoint ;
    //    @Value("${aliyun.oss.accessKeyId}")
    //    private String accessKeyId ;
    //    @Value("${aliyun.oss.accessKeySecret}")
    //    private String accessKeySecret ;
    //    @Value("${aliyun.oss.bucketName}")
    //    private String bucketName ;
    
        private AliOSSProperties aliOSSProperties;
    
        public AliOSSProperties getAliOSSProperties() {
            return aliOSSProperties;
        }
    
        public void setAliOSSProperties(AliOSSProperties aliOSSProperties) {
            this.aliOSSProperties = aliOSSProperties;
        }
    
        /**
         * 实现上传图片到OSS
         */
        public String upload(MultipartFile file) throws IOException {
            //获取阿里云OSS参数
            String endpoint = aliOSSProperties.getEndpoint();
            String accessKeyId = aliOSSProperties.getAccessKeyId();
            String accessKeySecret = aliOSSProperties.getAccessKeySecret();
            String bucketName = aliOSSProperties.getBucketName();
    
            // 获取上传的文件的输入流
            InputStream inputStream = file.getInputStream();
    
            // 避免文件覆盖
            String originalFilename = file.getOriginalFilename();
            String fileName = UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."));
    
            //上传文件到 OSS
            OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
            ossClient.putObject(bucketName, fileName, inputStream);
    
            //文件访问路径
            String url = endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + fileName;
            // 关闭ossClient
            ossClient.shutdown();
            return url;// 把上传到oss的路径返回
        }
    
    }
    
  3. 最后是创建一个 AliOSSConfiguration 配置类,用于将阿里云的 AliOSSUtils 对象存放如IOC容器中。
    package com.aliyun.oss;
    
    import org.springframework.boot.context.properties.EnableConfigurationProperties;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    @EnableConfigurationProperties(AliOSSProperties.class)
    public class AliOSSConfiguration {
    
        @Bean
        public AliOSSUtils aliOSSUtils(AliOSSProperties aliOSSProperties){
            AliOSSUtils aliOSSUtils = new AliOSSUtils();
            aliOSSUtils.setAliOSSProperties(aliOSSProperties);
            return aliOSSUtils;
        }
    }
    

接下来定义配置文件,用于IDEA找到AliOSSConfiguration 配置类对象(如下图)

3、总结

以上就是关于SpringBoot原理(@Conditional) — 三种自动配置方法、步骤详解。小编初次接触的时候还是觉得比较绕的,后面自己多思考动手还思维导图,总算是理解并且记住了。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

瑞_Java开发手册_(二)异常日志

文章目录 异常日志的意义(一) 错误码(二) 异常处理(三) 日志规约附&#xff1a;错误码列表 &#x1f64a;前言&#xff1a;本文章为瑞_系列专栏之《Java开发手册》的异常日志篇&#xff0c;本篇章主要介绍异常日志的错误码、异常处理、日志规约。由于博主是从阿里的《Java开发手…

逆水行舟 不进则退

目录 一、前言 二、2023年度总结 三、2024展望未来 一、前言 这是我从工作以来到现在最喜欢的一句话&#xff0c;我想把这句话送给自己也想送给大家。 2019年7月实习到现在已经过去了四年多&#xff0c;进入2024年也迎来了我工作生涯的第五个年头。 在这个行业里&#xff…

宠物空气净化器哪个牌子好?实惠的猫用空气净化器牌子推荐

对于养猫的朋友来说&#xff0c;猫咪掉毛绝对是一个让人头痛的问题。猫毛和皮屑会飘散在空气中&#xff0c;不仅会遍布全屋的各个角落&#xff0c;而且打扫起来也麻烦&#xff0c;特别是一些清理不了的猫毛&#xff0c;甚至还可能引起人的过敏反应&#xff0c;例如咳嗽和哮喘。…

PXIe-6396国产替代,8路AI(18位,14 MS/s/ch),2路A​O,24路DIO,PXI多功能I/O模块

PXIe&#xff0c;8路AI&#xff08;18位&#xff0c;14 MS/s/ch&#xff09;&#xff0c;2路A​O&#xff0c;24路DIO&#xff0c;PXI多功能I/O模块 PXIe-6396是一款同步采样的多功能DAQ设备。该模块提供了模拟 I/O、数字I/O、四个32位计数器和模拟和数字触发。板载NI-STC3定时…

RT-Thread GD32F4xx实现SD卡热插拔检测功能

GD32F470移植RT-Thread操作系统添加SD卡功能&#xff0c;增加SD卡热插拔检测 一、RT-Thread移植sd卡功能二、实现SD卡热插拔检测原理三、软件实现过程四、延展之ASSERT ERROR&#xff0c;即RT-Thread断言错误五、延展之STM32 SD卡热插拔检测六、结束语 一、RT-Thread移植sd卡功…

Java研学-过滤与监听

一 过滤器 Filter 1 介绍 Java Web 组件之一(Servlet 的功能)&#xff0c;可改变一个request和修改一个response。Filter不是Servlet&#xff0c;不能产生一个response&#xff0c;它是在一个request 到达Servlet之前预处理 request&#xff0c;也可以在response离开Servlet 后…

新一代数字原住民:市场痛点与“繁”思维应对之道

随着科技的迅速发展&#xff0c;尤其是互联网的普及&#xff0c;新一代数字原住民经营者已经逐渐成为市场的主力军。不同于传统的消费者&#xff0c;有着独特的消费习惯和心理需求。企业要在这激烈的市场竞争中获得优势&#xff0c;深入了解这一群体的特征和心理、行为&#xf…

【EMC专题】浪涌的成因与ICE 61000-4-5标准

什么是浪涌? 浪涌是一种无法预料的瞬态电压或电流尖峰,由附近的电子产品或是环境导致。 了解浪涌非常重要,因为浪涌有可能会导致设备的电气过应力损坏,造成系统故障等。 对于系统设计来说,重要的一点是我们如果无法控制浪涌的产生,那么只能通过将瞬态峰值电流导入到地,…

Pyside6/PyQt6中的QTimer类:轻松实现定时任务

文章目录 📖 介绍 📖🏡 环境 🏡📒 使用方法 📒📝 参数说明📝 常用方法⚓️ 相关链接 ⚓️📖 介绍 📖 在PySide/PyQt框架中,QTimer是一个核心类,主要用于在指定的间隔时间后触发某些事件。QTimer为开发者提供了一种处理和调度重复或单次动作的简便方式。 …

CSP网络结构实战 - 降低计算量的特征融合方式

CSP网络结构实战 - 降低计算量的特征融合方式 CSP网络结构实战 - 降低计算量的特征融合方式0. 引言1. CSP网络结构简介1.1 核心思想1.2 解决的问题 2. 实验验证2.1 CSP网络模型构建2.2 数据读取与预处理2.3 模型训练与验证 3. 对比实验4. 结果与总结 CSP网络结构实战 - 降低计算…

change事件传递多个参数

1.传递value页面参数 change"handleChange($event,123)" 2.传递选中的keyvalue或是选中的item 我用的是a-auto-complete&#xff0c;试验了用a-select也可以 就是在option里面&#xff0c;:value"JSON.stringify(d)" 然后在eval(( value ))转化就可…

Python中如何简化if...else...语句

一、引言 我们通常在Python中采用if...else..语句对结果进行判断&#xff0c;根据条件来返回不同的结果&#xff0c;如下面的例子。这段代码是一个简单的Python代码片段&#xff0c;让用户输入姓名并将其赋值给变量user_input。我们能不能把这几行代码进行简化&#xff0c;优化…

CTFhub-HTTP响应包源代码查看

CTFhub-Web-Web前置技能-“HTTP响应包源代码查看” 题目分析 页面空白&#xff0c;想到flag也许在源代码中 解题过程 F12&#xff0c;在element中&#xff0c;看到html代码&#xff0c;在其body中找到flag

对闭包的理解

概念&#xff1a; 一个函数对周围状态的引用捆绑在一起&#xff0c;闭包让开发者可以从内部函数访问外部 函数的作用域 简单理解&#xff1a;闭包 内层函数 外层函数的变量 一个函数对周围状态的引用捆绑在一起&#xff0c;闭包让开发者可以从内部函数访问外部 函数的作…

10.9.2 std::function 存储函数对象 Page184

41行&#xff0c;pending只是inc的复制品&#xff0c;所以43&#xff0c;44行&#xff0c;不会改变inc()的值 demo_function2()的运行结果&#xff1a; 59行&#xff0c;pending是inc的引用&#xff0c;所以61,62行将会改变inc()的值

如何在Windows 10/11的防火墙中禁止和允许某个应用程序,这里提供详细步骤

想阻止应用程序访问互联网吗&#xff1f;以下是如何通过简单的步骤阻止和允许Windows防火墙中的程序。​ 一般来说&#xff0c;大多数用户永远不需要担心应用程序访问互联网。然而&#xff0c;在某些情况下&#xff0c;你需要限制应用程序访问互联网。 例如&#xff0c;有问题…

webstorm最新版 激活 成功了

使用webstorm开发工具 很完美&#xff0c;第一次用webstorm IDE 开发工具就完美的激活了&#xff0c;你也不妨试试 链接地址&#xff1a;http://mano100.cn/thread-1942-1-1.html 激活后如下

Django数据库选移的preserve_default=False是什么意思?

有下面的迁移命令&#xff1a; migrations.AddField(model_namemovie,namemov_group,fieldmodels.CharField(defaultdjango.utils.timezone.now, max_length30),preserve_defaultFalse,),迁移命令中的preserve_defaultFalse是什么意思呢&#xff1f; 答&#xff1a;如果模型定…

Vue-Router 路径匹配与重定向

一、效果与描述 通过设置路由匹配同时设置重定向&#xff0c;让输错的网址重定向到指定页面&#xff0c;例如在网页输入网页地址把路径进行任意修改&#xff0c;重定向到登录页面。 二、Vue-Router代码 import { createRouter, createWebHashHistory } from vue-routerimport …

二、MySQL安装

目录 1、双击mysql8的安装向导 2、分为首次安装和再安装 1&#xff09;、首次安装 &#xff08;1&#xff09;如果是首次安装mysql系列的产品&#xff0c;需要先安装mysql产品的安装向导 &#xff08;2&#xff09;选择安装模式 2&#xff09;、不是首次安装 &#xff0…