• 手写自定义springboot-starter,感受框架的魅力和原理


    一、前言

    Springboot的自动配置原理,面试中经常问到,一直看也记不住,不如手写一个starter,加深一下记忆。
    看了之后发现大部分的starter都是这个原理,实践才会记忆深刻。
    核心思想:约定大于配置

    二、初探starter启动原理

    我们直接看看官网的starter是怎么设计的,仿照这写一个就行了!

    我们Ctrl点击spring-boot-starter-web,进入内部pom,我们发现里面有个

    <dependency>
      <groupId>org.springframework.bootgroupId>
      <artifactId>spring-boot-starterartifactId>
      <version>2.5.3version>
      <scope>compilescope>
    dependency>
    

    在此Ctrl点击spring-boot-starter进入starter内部pom:
    我们发现之后干活的就是这个包依赖:

    <dependency>
      <groupId>org.springframework.bootgroupId>
      <artifactId>spring-boot-autoconfigureartifactId>
      <version>2.5.3version>
      <scope>compilescope>
    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.wanggroupId>
            <artifactId>spring-boot-autoconfigureartifactId>
            <version>0.0.1-SNAPSHOTversion>
        dependency>
    dependencies>
    

    在这里插入图片描述

    2. spring-boot-autoconfigure pom配置

    <properties>
        <java.version>1.8java.version>
        <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
        <spring-boot.version>2.3.7.RELEASEspring-boot.version>
    properties>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starterartifactId>
            <version>${spring-boot.version}version>
        dependency>
        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
            <version>1.18.24version>
        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.wanggroupId>
        <artifactId>spring-boot-starterartifactId>
        <version>1.0-SNAPSHOTversion>
    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了!

    可以看下一小编的微信公众号,和网站文章首发看,欢迎关注!!

    点击访问!小编自己的网站,里面也是有很多好的文章哦!

  • 相关阅读:
    互联网摸鱼日报(2023-09-04)
    力扣labuladong——一刷day44
    SpringBoot + JWT + Redis 开源知识社区系统
    软件测试面试题及答案解析,2022最强版
    Flink实时数仓之用户埋点系统(一)
    模块化CSS
    金融行业数据库类应用分布式存储的评测方法与实践经验
    【驱动开发】实现三盏灯的控制,编写应用程序测试
    【JavaEE进阶序列 | 从小白到工程师】JavaEE中的静态方法定义、方法重载要求、return作用详解
    Mybatis的Mapper文件报错:Tag name expected
  • 原文地址:https://www.cnblogs.com/wang1221/p/16808653.html