手写自定义springboot-starter,感受框架的魅力和原理
一、前言
Springboot的自动配置原理,面试中经常问到,一直看也记不住,不如手写一个starter,加深一下记忆。
看了之后发现大部分的starter都是这个原理,实践才会记忆深刻。
核心思想:约定大于配置。
二、初探starter启动原理
我们直接看看官网的starter是怎么设计的,仿照这写一个就行了!
我们Ctrl点击<artifactId>spring-boot-starter-web</artifactId>,进入内部pom,我们发现里面有个
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.5.3</version>
<scope>compile</scope>
</dependency>
在此Ctrl点击<artifactId>spring-boot-starter</artifactId>进入starter内部pom:
我们发现之后干活的就是这个包依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>2.5.3</version>
<scope>compile</scope>
</dependency>

我们现在创建两个项目即可:
- spring-boot-starter(启动器)
- spring-boot-starter-autoconfigure(自动配置包)
小编看到官方这么写的提醒,大家可以按照官网的进行起名称,不要学小编哈!!
您应该确保为您的启动器提供适当的命名空间。不要以 . 开头的模块名称spring-boot,即使您使用不同的 Maven groupId。我们将来可能会为您自动配置的内容提供官方支持。
根据经验,您应该在启动器之后命名组合模块。例如,假设您正在为“acme”创建一个启动器,并且您命名自动配置模块acme-spring-boot和启动器acme-spring-boot-starter。如果您只有一个模块将两者结合起来,请将其命名为acme-spring-boot-starter.
三、项目搭建
1. 新建空白项目

输入总的项目名称

在空白项目里新建两个,这里可以分开单独建立,这里小编跟着雷神一样了,就不单独建立项目了!!

2. 新建maven项目

包名和名称:

3. 新建springboot项目

4. 项目架构
这里把没有用的都删除了!!可以不删

四、配置
1. 在starter项目中引入自己的autoconfigure依赖
就是上面建立项目的设置的
<dependencies>
<dependency>
<groupId>com.wang</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>

2. spring-boot-autoconfigure pom配置
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.3.7.RELEASE</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
</dependency>
</dependencies>
还是把没用的东西删除了,剩余如下图:

五、编写autoconfigure项目
1. 配置一个bean
首先删除了自动启动类,咱们用不到,
在spring-boot-autoconfigure项目中新建一个bean,此时不需要让这个bean在容器中,我们写一个自己配置,让他自动加入到容器中。
这就是自动配置的思想
/**
* 这里不需要让在容器中,我们写一个自己配置,让他自动加入到容器中
* @author wangzhenjun
* @date 2022/10/14 16:26
*/
public class HelloService {
@Autowired
private MyProperties myProperties;
public String HelloWord (String username){
return myProperties.getPrefix() + username + myProperties.getSuffix();
}
}
2. 编写一个配置文件
这里为了获取配置文件中的属性值,springboot自动配置源码里大部分都是,这样实现在一个配置文件中书写,其他的可以按照开头获取到属性和值!!
/**
* @author wangzhenjun
* @date 2022/10/14 16:28
*/
@Data
@ConfigurationProperties("wang.name")
public class MyProperties {
private String prefix;
private String suffix;
}
3. 编写自动配置
import com.wang.springbootautoconfigure.properties.MyProperties;
import com.wang.springbootautoconfigure.service.HelloService;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author wangzhenjun
* @date 2022/10/14 16:33
*/
@Configuration
//没有这个bean的时候才会生效
@ConditionalOnMissingBean(HelloService.class)
// 加载配置文件,让它成为容器中的bean
@EnableConfigurationProperties(MyProperties.class)
public class ServiceAutoConfiguration {
/**
* 把刚刚写的服务,加入到容器中
*/
@Bean
public HelloService helloService (){
return new HelloService();
}
}
主要就是condition下的几个注解,来完成bean是否加入到容器中:
常用的:
- @ConditionalOnClass
- @ConditionalOnMissingClass
- @ConditionalOnBean
- @ConditionalOnMissingBean
- @ConditionalOnProperty

4. 新建spring.factories
我们看到源码里自动配置,就是从这个文件获取加载,所以我们模仿这新建一个,这样就可以扫描加入容器中!!

如果是springboot2.7以上就是:
文件夹名称:META-INF.spring
文件名称:org.springframework.boot.autoconfigure.AutoConfiguration.imports

里面直接写全类名即可!
5. 打包
先把spring-boot-autoconfigure打包到本地库,在打包spring-boot-starter,顺序一定要有,不然找不到前者的包!!

六、测试
我们那一个新项目进行测试,新项目小编就不带大家建了!
1. 导入咱们的starter依赖
<dependency>
<groupId>com.wang</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
2. 添加配置文件
wang:
name:
prefix: hello
suffix: 886

3. 新建controller测试类
@RestController
@RequestMapping("/test")
public class TestController {
@Autowired
private HelloService helloService;
@GetMapping("/starter")
public String starter(){
return helloService.HelloWord("tom");
}
}
4. 测试访问
成功访问,不过中文是有乱码的,小编找不到解决方法,有懂的还请留言告知!!
主流程通了就行,慢慢理解了自动配置的魅力!
总流程应该就是这样的:
引入starter --- xxxAutoConfiguration --- 容器中放入组件 ---- 绑定xxxProperties ---- 配置项

中文是乱码,可能是servlet没有吧,有懂的可以留言告诉小编方案,谢谢大家!!

七、总结
一看会就,一动手就废!大家还是要做自己实操,不要眼高手低,这样才会有收获,根本就是约定大于配置+SPI发现机制!
还有就是一些经常出现在源码里的注解,大家记住就可以自己写starter了!
可以看下一小编的微信公众号,和网站文章首发看,欢迎关注!!

手写自定义springboot-starter,感受框架的魅力和原理的更多相关文章
- 手写一个springboot starter
springboot的starter的作用就是自动装配.将配置类自动装配好放入ioc容器里.作为一个组件,提供给springboot的程序使用. 今天手写一个starter.功能很简单,调用start ...
- Mybatis(一):手写一套持久层框架
作者 : 潘潘 未来半年,有幸与导师们一起学习交流,趁这个机会,把所学所感记录下来. 「封面图」 自毕业以后,自己先创业后上班,浮沉了近8年,内心着实焦躁,虽一直是走科班路线,但在技术道路上却始终没静 ...
- 手写一个简单到SpirngMVC框架
spring对于java程序员来说,无疑就是吃饭到筷子.在每次编程工作到时候,我们几乎都离不开它,相信无论过去,还是现在或是未来到一段时间,它仍会扮演着重要到角色.自己对spring有一定的自我见解, ...
- 自定义springboot - starter 实现日志打印,并支持动态可插拔
1. starter 命名规则: springboot项目有很多专一功能的starter组件,命名都是spring-boot-starter-xx,如spring-boot-starter-loggi ...
- 手写React的Fiber架构,深入理解其原理
熟悉React的朋友都知道,React支持jsx语法,我们可以直接将HTML代码写到JS中间,然后渲染到页面上,我们写的HTML如果有更新的话,React还有虚拟DOM的对比,只更新变化的部分,而不重 ...
- 手写koa-static源码,深入理解静态服务器原理
这篇文章继续前面的Koa源码系列,这个系列已经有两篇文章了: 第一篇讲解了Koa的核心架构和源码:手写Koa.js源码 第二篇讲解了@koa/router的架构和源码:手写@koa/router源码 ...
- 手写简化版SpringBoot
Springboot项目全部依赖注解的,web工程是如何启动的 1 首先引入了Tomcat依赖,然后用java代码启动Tomcat容器,默认Tomcat版本是8.5版本 2 Tomcat是实现了ser ...
- 手写内网穿透服务端客户端(NAT穿透)原理及实现
Hello,I'm Shendi. 这天心血来潮,决定做一个内网穿透的软件. 用过花生壳等软件的就知道内网穿透是个啥,干嘛用的了. 我们如果有服务器(比如tomcat),实际上我们在电脑上开启了服务器 ...
- 纯手写SpringMVC到SpringBoot框架项目实战
引言 Spring Boot其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置. 通过这种方式,springboot ...
随机推荐
- Odoo14 防暴力破解登录密码
1 # Odoo14 防暴力破解登录密码 2 # 主要工具:redis 3 # 实现思路:限制每个用户24小时内登录失败次数.连续超过5次失败后,需要等待一定时间后才能再次尝试登录 4 # 配置:在你 ...
- 程序思想中的冒泡法在python和1200PLC中scl高级编程中的应用
冒泡排序:是计算机科学领域里面的一种算法. header 这个算法名字的由来是因为在执行算法的时候越小的元素会经由交换慢慢"浮"到数列的顶端(升序或降序排列),就如同碳酸饮料中二氧 ...
- WebView2 通过 PuppeteerSharp 实现爬取 王者 壁纸 (案例版)
此案例是<.Net WebView2 项目,实现 嵌入 WEB 页面 Chromium内核>文的续集. 主要是针对WebView2的一些微软自己封装的不熟悉的API,有一些人已经对 Pup ...
- java-异常处理和线程的一些简单方法及使用
1.1 子类重写父类含有throws声明异常抛出的方法时的规则: 1.允许不再抛出任何异常. 2.仅抛出部分异常. 3.抛出父类方法抛出异常的子类型异常. 4.不可以抛出额外异常. 5.不能抛出父类方 ...
- 基于Vue3实现一个前端埋点上报插件并打包发布到npm
前端埋点对于那些营销活动的项目是必须的,它可以反应出用户的喜好与习惯,从而让项目的运营者们能够调整策略优化流程提高用户体验从而获取更多的$.这篇文章将实现一个Vue3版本的埋点上报插件,主要功能有 通 ...
- 【金九银十必问面试题】站在架构师角度分析问题,如何解决TCC中的悬挂问题
"如何解决TCC中的悬挂问题"! 一个工作了4年的Java程序员,去京东面试,被问到这个问题. 大家好,我是Mic,一个工作了14年的Java程序员 这个问题面试官想考察什么方面的 ...
- Java开发学习(三十二)----Maven多环境配置切换与跳过测试的三种方式
一.多环境开发 我们平常都是在自己的开发环境进行开发, 当开发完成后,需要把开发的功能部署到测试环境供测试人员进行测试使用, 等测试人员测试通过后,我们会将项目部署到生成环境上线使用. 这个时候就有一 ...
- C 语言 struct 第一个成员变量的妙用
一.双重身份 如下定义了一个 School 结构体: typedef struct School { int a; int b; }SCHOOL_S; SCHOOL_S stSch; 下面我们来输出一 ...
- Java 中HashMap 详解
本篇重点: 1.HashMap的存储结构 2.HashMap的put和get操作过程 3.HashMap的扩容 4.关于transient关键字 HashMap的存储结构 1. HashMap 总体是 ...
- 0.web理解
web前后端 网站的前端:通过用户肉眼看到的网站的布局内容,对网站的操作的功能,可以让用户可以直接接触与操作的部分. 用户通过访问前端的功能,前端分为 静态功能+动态功能 静态功能:静态功能则不会和后 ...