【Springboot】| 从深入自动配置原理到实现 自定义Springboot starter

目录

  • 一. 🦁 前言
  • 二. 🦁 Spring-boot starter 原理实现分析
    • 2.1 自动配置原理
  • 三. 🦁 操作实践
    • 3.1 项目场景
    • 3.2 搭建项目
    • 3.3 添加相关依赖
    • 3.4 删除一些不需要的东西
    • 3.5 发邮件工具类逻辑编写
    • 3.6 创建相关配置类
    • 3.7 创建 Spring.factories 文件
    • 3.8 目录结构展示
    • 3.9 打包
  • 四. 🦁 测试使用
  • 五. 🦁 总结

权限管理

一. 🦁 前言

Springboot starter是SpringBoot的一个重要概念,是“一站式服务 (one-stop)”的依赖 Jar 包包含 Spring 以及相关技术(比如 Redis)的所有依赖提供了自动配置的功能,开箱即用提供了良好的依赖管理,避免了包遗漏、版本冲突等问题。

简单来说, Springboot starter 提供了一种自动配置的机制,我们只需要将需要的Starter引入项目中,它就会自动为我们配置相关的依赖和配置。这使得开发人员可以更加关注业务逻辑的实现;现在我们来学习一下它的原理,以便后面能更清晰地实现。

二. 🦁 Spring-boot starter 原理实现分析

2.1 自动配置原理

在此之前,我们主要先来了解自动配置原理。

  1. 首先,我们可以把Springboot的启动流程简化成以下几步:
    Springboot启动流程
    在第3步加载处理所有配置类,其处理流程如下:
    在这里插入图片描述
    由上图可知道,加载配置类主要由两个注解完成,一个是@ComponentScan和@Import注解完成。
    其中,@ComponentScan其实就是@SpringbootApplication里面的注解之一,其作用是为了扫描其同级或者子包下的配置类(即与启动类同级或者子包下的配置类,这也是为啥我们做项目的时候,只需要导入一个starter就能实现某功能,其余工作都是Springboot帮我们干了),
    @Import 注解则在@EnableAutoConfiguration注解(其作用之一就是为了开启自动配置功能)里面,通过导入一个选择器ImportSelector的方式,提供了一种显式地从其它地方加载配置类的方式,这样可以避免使用性能较差的组件扫描(Component Scan)
    那么以上哪种注解适合用来实现自动配置呢?

无疑是使用导入选择器ImportSelector的@Import注解适合加载第三方jar包导入;

回到 @SpringbootApplication 注解,其注解组成如下:
在这里插入图片描述
而@EnableAutoConfiguration则是开启自动配置的核心注解,它由以下注解组成:
在这里插入图片描述
它通过导入AutoConfigurationImportSelector.class来实现自动配置;
而AutoConfigurationImportSelector类则是基于SpringFactories机制来实现的,现在来看一下它的主要源码:
在这里插入图片描述
getAutoConfigurationEntry(annotationMetadata)方法如下:
在这里插入图片描述
我们主要来看一下getCandidateConfigurations(annotationMetadata, attributes)方法:

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {List<String> configurations = new ArrayList(SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader()));ImportCandidates.load(AutoConfiguration.class, this.getBeanClassLoader()).forEach(configurations::add);Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories nor in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you are using a custom packaging, make sure that file is correct.");return configurations;}

这个则是基于SpringFactories机制获得第三方jar包中所有自动配置类的方法。由代码可以知道,读取配置文件获取自动配置类时,使用的key是类EnableAutoConfiguration的全限定名。其主要流程如下:
在这里插入图片描述
最后总结一下:
在这里插入图片描述

这里狮子是学习了B站一个UP主的视频理解的,推荐给大家:码场安员外

三. 🦁 操作实践

3.1 项目场景

前面狮子写了一篇《【SpringBoot】| 邮箱发送验证码,你会了吗?》深受伙伴们捧场,今天我们基于这个基础上再来封装一下spring-boot-starter-mail发送邮件类型的starter,方便后续使用。

3.2 搭建项目

我们先来搭建一个Springboot项目;根据Springboot starter的命名规范,属于Spring官方的就以spring-boot-starter-xxx的形式命名,其他技术自动整合Springboot的则按照xxx-spring-boot-starter命名。现在狮子起名为lion-email-spring-boot-starter,提高识别度(很规范(bushi),如下:

在这里插入图片描述

3.3 添加相关依赖

先添加Lombokspring-boot-starter-mail Spring Confguration Processor依赖(很重要,后面会体现它的价值);
在这里插入图片描述

3.4 删除一些不需要的东西

  1. 测试依赖
    在这里插入图片描述
  2. 打包插件
    在这里插入图片描述
  3. 启动类
    启动类也用不着,可以删了;

3.5 发邮件工具类逻辑编写

这种工具类写法比较固定,并不需要去记忆,自己积累一个就好。

import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.stereotype.Component;import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Properties;/*** 发邮件工具类*/
@Data
@AllArgsConstructor
public final class MailUtils {private String USER; // 发件人邮箱地址private String PASSWORD; // 如果是qq邮箱可以使户端授权码/*** 发送邮件* @param to 收件人邮箱* @param text 邮件正文* @param title 标题*/public boolean sendMail(String to, String text, String title){try {final Properties props = new Properties();props.put("mail.smtp.auth", "true");props.put("mail.smtp.host", "smtp.qq.com");// 发件人的账号props.put("mail.user", USER);//发件人的密码props.put("mail.password", PASSWORD);// 构建授权信息,用于进行SMTP进行身份验证Authenticator authenticator = new Authenticator() {@Overrideprotected PasswordAuthentication getPasswordAuthentication() {// 用户名、密码String userName = props.getProperty("mail.user");String password = props.getProperty("mail.password");return new PasswordAuthentication(userName, password);}};// 使用环境属性和授权信息,创建邮件会话Session mailSession = Session.getInstance(props, authenticator);// 创建邮件消息MimeMessage message = new MimeMessage(mailSession);// 设置发件人String username = props.getProperty("mail.user");InternetAddress form = new InternetAddress(username);message.setFrom(form);// 设置收件人InternetAddress toAddress = new InternetAddress(to);message.setRecipient(Message.RecipientType.TO, toAddress);// 设置邮件标题message.setSubject(title);// 设置邮件的内容体message.setContent(text, "text/html;charset=UTF-8");// 发送邮件Transport.send(message);return true;}catch (Exception e){e.printStackTrace();}return false;}}

3.6 创建相关配置类

创建LionEmailConfig配置类,在这里面干两个事:
一是在配置类里实例化MailUtils类,并将邮箱地址以及授权码返回给mailUtils;
二是配置参数:一般配置参数都是在Spring Boot 的application.yml中。我们会定义一个前缀标识来作为名称空间隔离各个组件的参数。对应的组件会定义一个XXXProperties 来自动装配这些参数。自动装配的机制基于@ConfigurationProperties注解,请注意一定要显式声明你配置的前缀标识(prefix)
这里需要添加几个注解,如下:

  1. @Configuration:在这里进行自动配置的工作。可以使用条件注解(@ConditionalOnClass、@ConditionalOnProperty 等)来根据情况决定是否应用自动配置。
  2. @ConfigurationProperties(“lion.email”):用于将外部配置属性绑定到 Spring Boot 应用程序中的 Java 对象上。这里加了一个lion.email前缀,则表示在配置文件(例如yaml文件)中,lion.email前缀下的字段值都会加载到Java对象中。
import com.lion.emailstarter.utils.MailUtils;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;@Configuration
@ConfigurationProperties("lion.email")
@ComponentScan
@Data
public class LionEmailConfig {private String user = "2373489842@qq.com"; // 发件人邮箱地址private String password = "abc-kpi"; // 如果是qq邮箱可以使户端授权码@Beanpublic MailUtils mailUtils(){return new MailUtils(user,password);}
}

3.7 创建 Spring.factories 文件

  1. 在 src/main/resources 目录下,创建一个名为 META-INF/spring.factories 的文件。
    在这里插入图片描述
  2. 文件里面的内容为(写法很单一,cv即可):
# spring boot starter
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.lion.emailstarter.LionEmailConfig

3.8 目录结构展示

在这里插入图片描述

3.9 打包

如下:
在这里插入图片描述
在这里插入图片描述
显示成功则说明该starter已经打包到本地的版本库中,starter编写完成。

四. 🦁 测试使用

随便找一个SpringBoot项目,

  1. 导入刚刚创建好的lion-email-spring-boot-starter依赖
  <dependency><groupId>com.lion</groupId><artifactId>lion-email-spring-boot-starter</artifactId><version>0.0.1-SNAPSHOT</version>
<dependency>
  1. 参数编写
    我们在yaml文件编写相关参数:
    当我们输入lion的时候就会弹出相关提示,这是因为前面3.3节我们添加了Spring Confguration Processor的缘故,自动生成配置的代码提示。
  2. 测试
@SpringBootTest
class LionTelecomsApplicationTests {@Autowiredprivate MailUtils mailUtils;@Testvoid contextLoads() {mailUtils.sendMail("2373489842@qq.com","有内鬼, 终止交易!","测试starter");}
}
  1. 测试结果
    在这里插入图片描述

五. 🦁 总结

这个技能对你有用么??有用点个赞,咱们下期见!


在这里插入图片描述

🦁 其它优质专栏推荐 🦁

🌟《Java核心系列(修炼内功,无上心法)》: 主要是JDK源码的核心讲解,几乎每篇文章都过万字,让你详细掌握每一个知识点!

🌟 《SpringBoot 源码剥析核心系列》:一些场景的Springboot源码剥析以及常用Springboot相关知识点解读

欢迎加入狮子的社区:『Lion-编程进阶之路』,日常收录优质好文

更多文章可持续关注上方🦁的博客,2023咱们顶峰相见!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

spark中排查Premature EOF: no length prefix available

报错信息 /07/22 10:20:28 WARN DFSClient: Error Recovery for block BP-888461729-172.16.34.148-1397820377004:blk_15089246483_16183344527 in pipeline 172.16.34.64:50010, 172.16.34.223:50010: bad datanode 172.16.34.64:50010 [DataStreamer for file /bdp/data/u9…

docker高级(mysql主从复制)

数据库密码需要设置成自己的&#xff01;&#xff01;&#xff01; 1、创建容器master13307 #docker pulldocker run -p 13307:3306 --name mysql-master \ --privilegedtrue \ -v /mysql/mysql-master/log:/var/log/mysql \ -v /mysql/mysql-master/data:/var/lib/mysql \ -…

python3对接godaddy API,实现自动更改域名解析(DDNS)

python3对接godaddy API&#xff0c;实现自动更改域名解析&#xff08;DDNS&#xff09; 文章开始前&#xff0c;先解释下如下问题&#xff1a; ①什么是域名解析&#xff1f; 域名解析一般是指通过一个域名指向IP地址&#xff08;A解析&#xff09;&#xff0c;然后我们访问…

C++图形界面编程-MFC

C控制台程序是命令行黑框&#xff0c;如果要写一个图形界面&#xff0c;VS也提供了图形界面编程MFC。建项目的时候选如下选项&#xff1a; 类似于QT。 问&#xff1a;那么MFC项目的运行入口main()或WinMain()在哪里呢&#xff1f; 答&#xff1a;其实&#xff0c;在MFC应用程…

【1++的数据结构】之map与set(一)

&#x1f44d;作者主页&#xff1a;进击的1 &#x1f929; 专栏链接&#xff1a;【1的数据结构】 文章目录 一&#xff0c;关联式容器与键值对二&#xff0c;setset的使用 三&#xff0c;mapmap的使用 四&#xff0c;multiset与multimap 一&#xff0c;关联式容器与键值对 像l…

视频云存储/安防监控视频AI智能分析网关V3:抽烟/打电话功能详解

人工智能技术已经越来越多地融入到视频监控领域中&#xff0c;近期我们也发布了基于AI智能视频云存储/安防监控视频AI智能分析平台的众多新功能&#xff0c;该平台内置多种AI算法&#xff0c;可对实时视频中的人脸、人体、物体等进行检测、跟踪与抓拍&#xff0c;支持口罩佩戴检…

redux中间件理解,常见的中间件,实现原理。

文章目录 一、Redux中间件介绍1、什么是Redux中间件2、使用redux中间件 一、Redux中间件介绍 1、什么是Redux中间件 redux 提供了类似后端 Express 的中间件概念&#xff0c;本质的目的是提供第三方插件的模式&#xff0c;自定义拦截 action -> reducer 的过程。变为 actio…

Wireshark数据抓包分析之HTTP协议

一、实验目的&#xff1a; 主要时熟悉wireshark的使用 二、预备知识&#xff1a; HTTP协议的相关知识 what fk&#xff0c;原来只要在右页点击切换&#xff0c;就可以开启2台不同的机器欸&#xff01;nice 三、实验过程&#xff1a; 1.在机器1中通过管理员身份运行hfs之后&a…

第七周第七天学习总结 | MySQL入门及练习学习第二天

实操练习&#xff1a; 1.创建一个名为 cesh的数据库 2.在这个数据库内 创建一个名为 xinxi 的表要求该表可以包含&#xff1a;编号&#xff0c;姓名&#xff0c;备注的信息 3.为 ceshi 表 添加数据 4.为xinxi 表的数据设置中文别名 5.查询 在 xinxi 表中编号 为2 的全部…

Navicat for Mysql 显示 emoji 表情符号乱码问题 — 其它乱码情况都可参考

系统环境&#xff1a; 操作系统&#xff1a;MAC OS 10.11.6 MySQL&#xff1a;Server version: 5.6.21 MySQL Community Server (GPL) Navicat for MySQL: version 9.3.1 - standard 1、问题发现 在客户端执行用户注册&#xff0c;用户名包括 emoji 表情符号&#xff0c;注册完…

线性代数的学习和整理14: 线性方程组求解

目录 1 线性方程组 2 有解&#xff0c;无解 3 解的个数 1 线性方程组 A*xy 3根直线的交点&#xff0c;就是解 无解的情况 无解&#xff1a; 三线平行无解&#xff1a;三线不相交 有解 有唯一解&#xff1a;三线相交于一点有无数解&#xff1a;三条线重叠 2 齐次线性方程组…

软件测试的方法有哪些?

软件测试 根据利用的被测对象信息的不同&#xff0c;可以将软件测试方法分为&#xff1a;黑盒测试、灰盒测试、白盒测试。 1、白盒测试 1&#xff09;概念&#xff1a;是依据被测软件分析程序内部构造&#xff0c;并根据内部构造分析用例&#xff0c;来对内部控制流程进行测试…

LabVIEW软件安装包分享(附安装教程)

目录 一、软件简介 二、软件下载 一、软件简介 LabVIEW&#xff08;Laboratory Virtual Instrument Engineering Workbench&#xff09;是由美国National Instruments&#xff08;简称NI&#xff09;公司开发的一款图形化编程工具&#xff0c;广泛应用于测试、测量和控制系统…

【深度学习】实验03 特征处理

文章目录 特征处理标准化归一化正则化 特征处理 标准化 # 导入标准化库 from sklearn.preprocessing import StandardScalerfrom matplotlib import gridspec import numpy as np import matplotlib.pyplot as plt import warnings warnings.filterwarnings("ignore&quo…

Tomcat 部署时 war 和 war exploded区别

在 Tomcat 调试部署的时候&#xff0c;我们通常会看到有下面 2 个选项。 是选择war还是war exploded 这里首先看一下他们两个的区别&#xff1a; war 模式&#xff1a;将WEB工程以包的形式上传到服务器 &#xff1b;war exploded 模式&#xff1a;将WEB工程以当前文件夹的位置…

基于风险的漏洞管理

基于风险的漏洞管理涉及对即将被利用的漏洞的分类响应&#xff0c;如果被利用&#xff0c;可能会导致严重后果。本文详细介绍了确定漏洞优先级时要考虑的关键风险因素&#xff0c;以及确保基于风险的漏洞管理成功的其他注意事项。 什么是基于风险的漏洞管理对基于风险的漏洞管…

prometheus监控JVM(接入tomcat)

一、整合jmx_exporter及tomcat 1、 jmx_exporter下载地址 https://github.com/prometheus/jmx_exporter/releases 2、 tomcat配置文件下载地址 https://github.com/prometheus/jmx_exporter/blob/main/example_configs/tomcat.yml 3、创建tomcat_exporter目录 [rootlocalhost ~…

前端需要理解的性能优化知识

优化的目的是展示更快、交互响应快、页面无卡顿情况。 1 性能指标 2 分析方法 使用 ChromeDevTool 作为性能分析工具来观察页面性能情况。其中Network观察网络资源加载耗时及顺序&#xff0c;Performace观察页面渲染表现及JS执行情况&#xff0c;Lighthouse对网站进行整体评分…

【算法训练-双指针】最长无重复子串(数组)

废话不多说&#xff0c;喊一句号子鼓励自己&#xff1a;程序员永不失业&#xff0c;程序员走向架构&#xff01;本篇Blog的主题是最长无重复子串或最长无重复子数组&#xff0c;这类题目出现频率还是很高的。 最长无重复子数组 先来看看数组数据结构的题目 题干 输入&#…

Android studio 软件git使用

在 test 分支添加的方法 , 现在切换到 master分支 总共 2 个分支 , 当前的分支是 test 出现了 先试一下 force checkout , 尝试之后发现 , 你更改没有带过来 , 以为哪个类在master分支没有 , 所以这边也没有 , 切回分支 test 发现之前的跟改没有 , 这样即可以找回 继续切换…