• 手撸一个SpringBoot-Starter


    1. 简介

    通过了解SpringBoot的原理后,我们可以手撸一个spring-boot-starter来加深理解。

    1.1 什么是starter

    spring官网解释

    • starters是一组方便的依赖描述符(根据功能特点将用到的依赖标记封装到同一个pom中),可以将其包含在应用程序中。
    • 通过starters可以获取所需的所有Spring和相关技术的一站式服务,而无需搜索示例代码或复制粘贴加载的依赖项描述符。

    1.2 命名规则

    官方首发都遵循类似的命名模式:spring-boot-starter-*,其中*是特定类型的应用程序,例如: spring-boot-starter-web

    第三方启动器不应以spring-boot开头,因为它是为官方 Spring Boot 工件保留的,相反,第三方启动器通常以项目名称开头,例如:ldx.spring-boot-starter

    1.3 代码结构

    如图,官方的spring-boot-starter Jar中其实没有包含代码,starter其实是就是一组依赖描述的集合,而其中主要包含的就是autoconfigure模块和一些必要的依赖模块。

    spring-boot官方所有的auto-configuration-classes

    springboot官方的starter中依赖如下:

    当我们进入到官方autoconfiguration中查看redis配置源码如下,而我们待会儿也会模仿RedisAutoConfiguration写一个自己的starter

    2. 开撸

    spring官方学习地址

    2.1 项目结构

    结构说明:

    ├── redis-spring-boot-starter  # 自定义的starter模块
    │   ├── pom.xml
    ├── spring-boot-autoconfigure # 自定义的auto configure模块
    │   ├── pom.xml
    │   └── src
    │       └── main
    │           ├── java
    │           │   └── com
    │           │       └── ldx
    │           │           └── autoconfigure
    │           │               └── config
    │           │                   ├── RedisAutoConfiguration.java # redis 自动配置类
    │           │                   └── RedisProperty.java  # redis property 参数绑定类
    │           └── resources
    │               └── META-INF
    │                   └── spring.factories # spring自动装配配置文件
    └── test # 功能测试模块
        ├── pom.xml
        ├── src
        │   └── main
        │       ├── java
        │       │   └── com
        │       │       └── ldx
        │       │           └── test
        │       │               └── TestApplication.java # 启动类
        │       └── resources
        │           └── application.yaml # 资源文件
    

    2.2 spring-boot-autoconfigure

    正如简介中提到的一样,该模块用于提供autoconfigure核心功能,通过META-INF/spring.factories实现对RedisAutoConfiguration.class的扫描,然后在RedisAutoConfiguration.class中实现Jedis的条件化注入,从而实现springboot的自动装配功能。

    2.2.1 导入依赖

    spring-boot-autoconfigure-processor是一个注释处理器,依赖用于生成META-INF/spring-autoconfigure-metadata.properties并且被包含在项目 jar 中,其文件记录了当前classpath下所有的autoconfigure的元信息,在项目启动时会先扫描此文件(如果存在),此文件有助于缩短启动时间,但不是程序正常运行所必需的。

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    	<modelVersion>4.0.0</modelVersion>
    	<parent>
    		<groupId>org.springframework.boot</groupId>
    		<artifactId>spring-boot-starter-parent</artifactId>
    		<version>2.5.3</version>
    		<relativePath/> <!-- lookup parent from repository -->
    	</parent>
    	<groupId>com.ldx</groupId>
    	<artifactId>spring-boot-autoconfigure</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
    	<name>spring-boot-autoconfigure</name>
    	<description>自定义的 spring-boot-autoconfigure</description>
    	<properties>
    		<java.version>1.8</java.version>
    	</properties>
    	<dependencies>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.projectlombok</groupId>
    			<artifactId>lombok</artifactId>
    			<optional>true</optional>
    		</dependency>
    		<!--引入redis客户端 jedis依赖-->
    		<dependency>
    			<groupId>redis.clients</groupId>
    			<artifactId>jedis</artifactId>
    			<!-- 防止当前依赖被传递引用 -->
    			<optional>true</optional>
    		</dependency>
    		<!--自动配置注解注释处理器,
    		用于生成META-INF/spring-autoconfigure-metadata.properties包含在项目中-->
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-autoconfigure-processor</artifactId>
    			<optional>true</optional>
    		</dependency>
    	</dependencies>
    </project>
    
    

    2.2.2 RedisProperty

    import lombok.Data;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    
    /**
     * redis 属性注入类
     *
     * @author ludangxin
     * @date 2021/8/1
     */
    @Data
    // 用于读取配置文件中的链接信息
    @ConfigurationProperties(prefix = "redis")
    public class RedisProperty {
       private String host = "localhost";
    
       private int port = 6379;
    }
    

    2.2.3 RedisAutoConfiguration

    import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
    import org.springframework.boot.context.properties.EnableConfigurationProperties;
    import org.springframework.context.annotation.Bean;
    import redis.clients.jedis.Jedis;
    
    /**
     * redis 自动化配置类
     *
     * @author ludangxin
     * @date 2021/8/1
     */
    @ConditionalOnClass(Jedis.class)
    @EnableConfigurationProperties(RedisProperty.class)
    public class RedisAutoConfiguration {
    
       @Bean
       @ConditionalOnMissingBean(Jedis.class)
       public Jedis jedis(RedisProperty redisProperty) {
          return new Jedis(redisProperty.getHost(), redisProperty.getPort());
       }
    }
    

    2.2.4 spring.factories

    resources下创建META-INF/spring.factoriesEnableAutoConfiguration指向RedisAutoConfiguration

    org.springframework.boot.autoconfigure.EnableAutoConfiguration = 
      com.ldx.autoconfigure.config.RedisAutoConfiguration
    

    2.2.5 安装依赖

    将当前模块打成Jar安装到本地仓库。

    2.3 redis-spring-boot-starter

    2.3.1 导入依赖

    在其pom中添加我们刚才创建的spring-boot-autoconfigure模块,并且添加jedis模块(autoconfigure模块中jedis不允许传递依赖因为将来autoconfigure文件中的会有各种各样的第三方自动化配置,不可能全部传递依赖,只能是用到哪个的时候就自行在starter中添加哪个即可)

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
       <modelVersion>4.0.0</modelVersion>
       <groupId>com.ldx</groupId>
       <artifactId>redis-spring-boot-starter</artifactId>
       <version>0.0.1-SNAPSHOT</version>
       <name>redis-spring-boot-starter</name>
       <description>customize starter</description>
       <properties>
          <java.version>1.8</java.version>
       </properties>
       <dependencies>
          <!--引用自己创建的spring-boot-autoconfigure model-->
          <dependency>
             <groupId>com.ldx</groupId>
             <artifactId>spring-boot-autoconfigure</artifactId>
             <version>0.0.1-SNAPSHOT</version>
          </dependency>
          <!-- 引用jedis客户端 -->
          <dependency>
             <groupId>redis.clients</groupId>
             <artifactId>jedis</artifactId>
             <version>3.6.3</version>
          </dependency>
       </dependencies>
    </project>
    

    2.3.2 安装依赖

    将当前模块打成Jar安装到本地仓库。

    2.4 test

    test模块为测试模块,测试starter功能。

    2.4.1 导入依赖

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
       <modelVersion>4.0.0</modelVersion>
       <parent>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-parent</artifactId>
          <version>2.5.3</version>
          <relativePath/> <!-- lookup parent from repository -->
       </parent>
       <groupId>com.ldx</groupId>
       <artifactId>test</artifactId>
       <version>0.0.1-SNAPSHOT</version>
       <name>test</name>
       <description>测试springboot-starter</description>
       <properties>
          <java.version>1.8</java.version>
       </properties>
       <dependencies>
          <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter</artifactId>
          </dependency>
          <dependency>
             <groupId>org.projectlombok</groupId>
             <artifactId>lombok</artifactId>
             <optional>true</optional>
          </dependency>
          <!-- 引用自己创建的redis-starter -->
          <dependency>
             <groupId>com.ldx</groupId>
             <artifactId>redis-spring-boot-starter</artifactId>
             <version>0.0.1-SNAPSHOT</version>
          </dependency>
       </dependencies>
       <build>
          <plugins>
             <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
             </plugin>
          </plugins>
       </build>
    </project>
    

    2.4.2 修改启动类

    package com.ldx.test;
    
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.ConfigurableApplicationContext;
    import redis.clients.jedis.Jedis;
    
    @Slf4j
    @SpringBootApplication
    public class TestApplication {
    
    	public static void main(String[] args) {
    	    ConfigurableApplicationContext applicationContext = SpringApplication.run(TestApplication.class, args);
                // 获取jedis bean
                Jedis jedis = applicationContext.getBean(Jedis.class);
                // add
    	    jedis.set("name", "张三");
    	    log.info(jedis.get("name"));
    	}
    
    }
    
    

    2.4.3 启动测试

    启动项目成功获取到了设置的数据。

      .   ____          _            __ _ _
     /\ / ___'_ __ _ _(_)_ __  __ _    
    ( ( )\___ | '_ | '_| | '_ / _` |    
     \/  ___)| |_)| | | | | || (_| |  ) ) ) )
      '  |____| .__|_| |_|_| |_\__, | / / / /
     =========|_|==============|___/=/_/_/_/
     :: Spring Boot ::                (v2.5.3)
    
    2021-08-03 23:08:44.531  INFO 13930 --- [           main] com.ldx.test.TestApplication             : Starting TestApplication using Java 1.8.0_261 on ludangxindeMacBook-Pro.local with PID 13930 (/Users/ludangxin/workspace/idea/redis-starter/test/target/classes started by ludangxin in /Users/ludangxin/workspace/idea/redis-starter)
    2021-08-03 23:08:44.532  INFO 13930 --- [           main] com.ldx.test.TestApplication             : No active profile set, falling back to default profiles: default
    2021-08-03 23:08:45.062  INFO 13930 --- [           main] com.ldx.test.TestApplication             : Started TestApplication in 0.901 seconds (JVM running for 1.384)
    2021-08-03 23:08:45.072  INFO 13930 --- [           main] com.ldx.test.TestApplication             : 张三
    

    这时我们在test模块的application.yaml文配置redis.port=123测试autoconfigure模块能不能正常的获取配置信息。
    启动项目报错如下:

    说明配置类正确的获取到了错误的配置信息,符合预期,打完收工。

    这时我们再回头看下spring-boot-autoconfigure-processor依赖生产的元信息文件如下:

    3. 小结

    spring-boot-starter的出现,大大的提升了我们项目的搭建速度和质量(我们仅需导入依赖坐标,然后在配置文件中进行简单的配置即可。再也不用因为依赖找不全,版本对不上,依赖冲突...而烦恼了),并且官方和第三方的starter简化了我们对中间操作(提供了通用的template,整合了对数据库比如jpa或者amqp等操作接口),简直不要太爽。

    当我们学习了如何创建自己的starter后,也可以封装我们自己的starter用于项目的建设和使用。

    SpringBoot内置Starter

    官方地址介绍地址 github源码地址

    名称 描述
    spring-boot-starter 核心启动器,包括自动配置支持、日志记录和 YAML
    spring-boot-starter-activemq 使用 Apache ActiveMQ 的 JMS 消息传递入门
    spring-boot-starter-amqp 使用 Spring AMQP 和 Rabbit MQ 的入门者
    spring-boot-starter-aop 使用 Spring AOP 和 AspectJ 进行面向方面编程的入门者
    spring-boot-starter-artemis 使用 Apache Artemis 进行 JMS 消息传递的入门者
    spring-boot-starter-batch 使用 Spring Batch 的启动器
    spring-boot-starter-cache 使用 Spring Framework 的缓存支持的 Starter
    spring-boot-starter-data-cassandra Starter 使用 Cassandra 分布式数据库和 Spring Data Cassandra
    spring-boot-starter-data-cassandra-reactive Starter 使用 Cassandra 分布式数据库和 Spring Data Cassandra Reactive
    spring-boot-starter-data-couchbase 使用 Couchbase 面向文档的数据库和 Spring Data Couchbase 的入门者
    spring-boot-starter-data-couchbase-reactive Starter 使用 Couchbase 面向文档的数据库和 Spring Data Couchbase Reactive
    spring-boot-starter-data-elasticsearch 使用 Elasticsearch 搜索和分析引擎以及 Spring Data Elasticsearch 的入门者
    spring-boot-starter-data-jdbc 使用 Spring Data JDBC 的入门者
    spring-boot-starter-data-jpa 将 Spring Data JPA 与 Hibernate 结合使用的入门者
    spring-boot-starter-data-ldap 使用 Spring Data LDAP 的入门者
    spring-boot-starter-data-mongodb 使用 MongoDB 面向文档的数据库和 Spring Data MongoDB 的入门者
    spring-boot-starter-data-mongodb-reactive Starter 使用 MongoDB 面向文档的数据库和 Spring Data MongoDB Reactive
    spring-boot-starter-data-neo4j 使用 Neo4j 图形数据库和 Spring Data Neo4j 的入门者
    spring-boot-starter-data-r2dbc 使用 Spring Data R2DBC 的启动器
    spring-boot-starter-data-redis 将 Redis 键值数据存储与 Spring Data Redis 和 Lettuce 客户端一起使用的入门者
    spring-boot-starter-data-redis-reactive 将 Redis 键值数据存储与 Spring Data Redis 反应式和 Lettuce 客户端一起使用的入门者
    spring-boot-starter-data-rest 使用 Spring Data REST 在 REST 上公开 Spring Data 存储库的启动器
    spring-boot-starter-freemarker 使用 FreeMarker 视图构建 MVC Web 应用程序的入门者
    spring-boot-starter-groovy-templates 使用 Groovy 模板视图构建 MVC Web 应用程序的入门者
    spring-boot-starter-hateoas 使用 Spring MVC 和 Spring HATEOAS 构建基于超媒体的 RESTful Web 应用程序的入门者
    spring-boot-starter-integration 使用 Spring Integration 的入门者
    spring-boot-starter-jdbc 将 JDBC 与 HikariCP 连接池一起使用的 Starter
    spring-boot-starter-jersey 使用 JAX-RS 和 Jersey 构建 RESTful Web 应用程序的初学者。替代方案spring-boot-starter-web
    spring-boot-starter-jooq 使用 jOOQ 访问 SQL 数据库的入门者。spring-boot-starter-data-jpa或的替代品spring-boot-starter-jdbc
    spring-boot-starter-json 读写json的Starter
    spring-boot-starter-jta-atomikos 使用 Atomikos 的 JTA 事务入门
    spring-boot-starter-mail 使用 Java Mail 的 Starter 和 Spring Framework 的电子邮件发送支持
    spring-boot-starter-mustache 使用 Mustache 视图构建 Web 应用程序的入门者
    spring-boot-starter-oauth2-client 使用 Spring Security 的 OAuth2/OpenID Connect 客户端功能的入门者
    spring-boot-starter-oauth2-resource-server 使用 Spring Security 的 OAuth2 资源服务器功能的入门者
    spring-boot-starter-quartz 使用 Quartz 调度器的启动器
    spring-boot-starter-rsocket 用于构建 RSocket 客户端和服务器的 Starter
    spring-boot-starter-security 使用 Spring Security 的入门者
    spring-boot-starter-test Starter 用于使用包括 JUnit Jupiter、Hamcrest 和 Mockito 在内的库测试 Spring Boot 应用程序
    spring-boot-starter-thymeleaf 使用 Thymeleaf 视图构建 MVC Web 应用程序的初学者
    spring-boot-starter-validation 将 Java Bean 验证与 Hibernate Validator 结合使用的入门工具
    spring-boot-starter-web 使用 Spring MVC 构建 Web(包括 RESTful)应用程序的入门者。使用 Tomcat 作为默认的嵌入式容器
    spring-boot-starter-web-services 使用 Spring Web 服务的入门者
    spring-boot-starter-webflux 使用 Spring Framework 的 Reactive Web 支持构建 WebFlux 应用程序的 Starter
    spring-boot-starter-websocket 使用 Spring Framework 的 WebSocket 支持构建 WebSocket 应用程序的 Starter

    除了应用程序启动器之外,以下启动器还可用于添加生产就绪功能:

    名称 描述
    spring-boot-starter-actuator 使用 Spring Boot 的 Actuator 的 Starter,它提供了生产就绪的特性来帮助你监控和管理你的应用程序

    最后,Spring Boot 还包括以下启动器,如果您想排除或交换特定的技术方面,可以使用它们:

    名称 描述
    spring-boot-starter-jetty 使用 Jetty 作为嵌入式 servlet 容器的启动器。替代方案spring-boot-starter-tomcat
    spring-boot-starter-log4j2 使用 Log4j2 进行日志记录的启动器。替代方案spring-boot-starter-logging
    spring-boot-starter-logging 使用 Logback 进行日志记录的启动器。默认日志记录启动器
    spring-boot-starter-reactor-netty 使用 Reactor Netty 作为嵌入式响应式 HTTP 服务器的启动器。
    spring-boot-starter-tomcat 使用 Tomcat 作为嵌入式 servlet 容器的启动器。使用的默认 servlet 容器启动器spring-boot-starter-web
    spring-boot-starter-undertow 使用 Undertow 作为嵌入式 servlet 容器的启动器。替代方案spring-boot-starter-tomcat
  • 相关阅读:
    使用iptables禁止外网访问tomcat的8080端口
    解决ie浏览器下载apk或ipa变为zip
    'ᄈ'
    centos上安装grafana
    vertica单节点故障恢复 Startup Failed, ASR Required
    vertica审计日志
    centos安装nginx1.17.9
    centos上nginx转发tcp请求
    centos 安装mysql8.0.16
    centos下导出docx为html
  • 原文地址:https://www.cnblogs.com/ludangxin/p/15096970.html
Copyright © 2020-2023  润新知