• 深入理解SpringBoot核心机制《spring-boot-starter》


    深入理解SpringBoot核心机制《spring-boot-starter》

    前言
    对于这几年java火爆天的springBoot我相信大家都有所使用过,在springBoot的项目中,pom文件引入最多的无非就是各种各样的srping-starter了。
    什么是 Starter 呢?为什么要使用Starter呢?
    你可以理解为一个可拔插式的插件(组件)。

    通过 Starter,能够简化以前繁琐的配置,无需过多的配置和依赖,它会帮你合并依赖,并且将其统一集成到一个 Starter 中,我们只需在 Maven 或 Gradle 中引入 Starter 依赖即可。SpringBoot 会自动扫描需要加载的信息并启动相应的默认配置。

    如果你想使用 redis 插件,你只需引入 spring-boot-starter-data-redis 即可;如果你想使用 mongodb,你只需引入 spring-boot-starter-data-mongodb 依赖即可。

    springBoot-starter是一个集成接合器,完成两件事:

    1、引入模块所需的相关jar包

    2、自动配置各自模块所需的属性

    SpringBoot 官方提供了大量日常企业应用研发各种场景的 spring-boot-starter 依赖模块。这些依赖模块都遵循着约定成俗的默认配置,并允许我们根据自身情况调整这些配置。

    20210728154315
    官方git地址:https://github.com/spring-projects/spring-boot/tree/2.5.x/spring-boot-project/spring-boot-starters

    starter启动原理:
    使用过springBoot项目的人应该都对@SpringBootApplication注解有所了解,那么我们看下源码:

    @SpringBootApplication注解源码:
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @SpringBootConfiguration
    @EnableAutoConfiguration
    @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
            @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
    public @interface SpringBootApplication
    
    其中@EnableAutoConfiguration注解源码:
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @AutoConfigurationPackage
    @Import(AutoConfigurationImportSelector.class)
    public @interface EnableAutoConfiguration 
    

    可以从源码看出关键功能是@Import注解导入自动配置功能类AutoConfigurationImportSelector类,主要方法getCandidateConfigurations()使用了SpringFactoriesLoader.loadFactoryNames()方法加载META-INF/spring.factories的文件(spring.factories声明具体自动配置)。
    自定义starter:

    Starter 命名规则

    Spring 官方定义的 Starter 通常命名遵循的格式为 spring-boot-starter-{name},例如 spring-boot-starter-data-mongodb。
    Spring 官方建议,非官方 Starter 命名应遵循 {name}-spring-boot-starter 的格式,例如,myjson-spring-boot-starter。
    pom文件配置如下:

    <?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.3.11.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.duxn</groupId>
        <artifactId>duxn-spring-boot-starter</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>duxn-spring-boot-starter</name>
        <description>Demo project for Spring Boot</description>
        <properties>
            <java.version>1.8</java.version>
        </properties>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-autoconfigure</artifactId>
            </dependency>
        </dependencies>
    
        <!-- 设置deploy的地址 -->
        <distributionManagement>
            <snapshotRepository>
                <id>maven-snapshots</id>
                <name>user snapshot</name>
                <url>maven仓库地址</url>
            </snapshotRepository>
            <repository>
                <id>maven-releases</id>
                <name>user release resp</name>
                <url>maven仓库地址/</url>
            </repository>
        </distributionManagement>
    
        <build>
            <finalName>${project.artifactId}-${project.version}</finalName>
    
            <plugins>
                <!-- 跳过测试用例 -->
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.22.0</version>
                    <configuration>
                        <skipTests>true</skipTests>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    
    </project>
    

    config配置如下:

    public class BaseConfig {
    
        @ConfigurationProperties(prefix = "fulu")
        @Data
        public static class FuluConfig {
            public String ichnbUrl = "可以设置默认值";
            public Boolean isCache = true;//是否缓存
            public Boolean isAuth = false;//是否校验身份信息
        }
    
        @ConfigurationProperties(prefix = "jwt")
        @Data
        public static class JWTConfig {
            public String issuer = "可以设置默认值";
    
            public String url = "可以设置默认值";
        }
    
        @ConfigurationProperties(prefix = "jwt.rpc")
        @Data
        public static class JWTRPCConfig {
            public String secret = "可以设置默认值";
        }
    
        @ConfigurationProperties(prefix = "oss")
        @Data
        public static class OSSConfig {
            private String accessId = "可以设置默认值";
            private String accessKey = "可以设置默认值";
            private String endPoint = "可以设置默认值";
            private String nameSpace = "可以设置默认值";
            private String packages = "可以设置默认值";
        }
    
    }
    

    核心配置类:

    @Configuration
    @AutoConfigureOrder(Integer.MAX_VALUE)
    @EnableAspectJAutoProxy(proxyTargetClass = true)
    @ConditionalOnClass({HttpUtils.class})
    @EnableConfigurationProperties({
            BaseConfig.JWTConfig.class,
            BaseConfig.JWTRPCConfig.class,
            BaseConfig.FuluConfig.class,
            BaseConfig.OSSConfig.class
    })
    @Slf4j
    public class StarterConfiguration {
    
        @Resource
        private BaseConfig.JWTConfig jwtConfig;
    
        @Resource
        private BaseConfig.JWTRPCConfig jwtrpcConfig;
    
        @Resource
        private BaseConfig.FuluConfig fuluConfig;
    
        @Resource
        private BaseConfig.OSSConfig ossConfig;
    
        @Bean
        public HttpUtils httpUtils() {
            return new HttpUtils(redisTemplate, jwtConfig, jwtrpcConfig, fuluConfig);
        }
    
    }
    

    spring.factory配置:

    org.springframework.boot.autoconfigure.EnableAutoConfiguration=
    com.duxn.starter.config.StarterConfiguration
    

    如需添加扫描可以在StarterConfiguration中注入@Bean或者直接在spring.factory追加扫描
    假设扫描类需要添加构造入参则只能在StarterConfiguration中注入@Bean

    此时一个spring-boot-starter已开发完毕。

    使用方式:

    pom文件引入
    
    <dependency>
        <groupId>com.duxn</groupId>
            <artifactId>duxn-spring-boot-starter</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
    
    yml文件配置
    fulu:
      ichnbUrl: 
      isCache: 
      isAuth: 
    jwt:
      issuer: 
      rpc:
        secret: 
      url: 
    oss:
      accessId: 
      accessKey: 
      endPoint: 
      nameSpace: 
      packages: 
    

    至此:一个自己的starer已完成!

    福禄·研发中心 福小雄
  • 相关阅读:
    JavaScript表单编程
    JavaScript事件模型
    DOM总结
    CSS3 媒体查询响应式布局
    BOM总结
    JS实现文字图片无缝滚动
    深入理解jQuery事件绑定机制
    被你忽略的jQuery常用方法“特异功能”
    关于BOM的学习总结
    Hello,World!
  • 原文地址:https://www.cnblogs.com/fulu/p/15260935.html
Copyright © 2020-2023  润新知