SpringBoot Starter缘起

时间:2022-10-29 07:07:26

SpringBoot通过SpringBoot Starter零配置自动加载第三方模块,只需要引入模块的jar包不需要任何配置就可以启用模块,遵循约定大于配置的思想。
那么如何编写一个SpringBoot Starter呢?我们需要考虑如下几个问题:

  1. 如何让SpringBoot发现我们编写的模块?
  2. 如何让模块读取SpringBoot的配置文件?
  3. 如果用户没有在配置文件中配置必要的配置项,如何默认禁用模块?
  4. 如何让SpringBoot知道模块有哪些配置项目,方便用户配置配置文件?

一.模块的发现

由于SpringBoot默认的包扫描路径是主程序所在包及其下面的所有子包里面的组件,引入的jar包下的类是不会被扫描的。那么如何去加载Starter的配置类呢?
SpringBoot约定会扫描Starter jar包META-INF目录下的spring.factories文件,只需要在spring.factories文件里配置要加载的类就可以了。下面的是Arthas的配置文件(arthas-spring-boot-starter-3.6.3.jar,Arthas是Alibaba开源的Java诊断工具。)。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.alibaba.arthas.spring.ArthasConfiguration,\ com.alibaba.arthas.spring.endpoints.ArthasEndPointAutoConfiguration

这样SpringBoot在启动的时候就会自动加载这些类存放到容器中管理。

二.模块读取SpringBoot的配置文件

ArthasConfiguration的源码:

@ConditionalOnProperty(
    name = {"spring.arthas.enabled"},
    matchIfMissing = true
)
@EnableConfigurationProperties({ArthasProperties.class})
public class ArthasConfiguration {
    @ConfigurationProperties(
        prefix = "arthas"
    )
    @ConditionalOnMissingBean(
        name = {"arthasConfigMap"}
    )
    @Bean
    public HashMap<String, String> arthasConfigMap() {
        return new HashMap();
    }

    @ConditionalOnMissingBean
    @Bean
    public ArthasAgent arthasAgent(@Autowired @Qualifier("arthasConfigMap") Map<String, String> arthasConfigMap, @Autowired ArthasProperties arthasProperties) throws Throwable {
        arthasConfigMap = StringUtils.removeDashKey(arthasConfigMap);
        ArthasProperties.updateArthasConfigMapDefaultValue(arthasConfigMap);
        String appName = this.environment.getProperty("spring.application.name");
        if (arthasConfigMap.get("appName") == null && appName != null) {
            arthasConfigMap.put("appName", appName);
        }

        Map<String, String> mapWithPrefix = new HashMap(arthasConfigMap.size());
        Iterator var5 = arthasConfigMap.entrySet().iterator();

        while(var5.hasNext()) {
            Map.Entry<String, String> entry = (Map.Entry)var5.next();
            mapWithPrefix.put("arthas." + (String)entry.getKey(), entry.getValue());
        }

        ArthasAgent arthasAgent = new ArthasAgent(mapWithPrefix, arthasProperties.getHome(), arthasProperties.isSlientInit(), (Instrumentation)null);
        arthasAgent.init();
        logger.info("Arthas agent start success.");
        return arthasAgent;
    }
}
我们发现类上面两个注解EnableConfigurationProperties和ConditionalOnProperty。这两个注解的作用如下:
  • EnableConfigurationProperties用来指定要加载的配置类,配置类用来加载SpringBoot的配置文件,SpringBoot配置文件中可以指定Arthas的启动参数。如果你不需要任何参数,则可以不指定EnableConfigurationProperties。
@ConfigurationProperties(
    prefix = "arthas"
)
public class ArthasProperties {
private String ip;
    private int telnetPort;
    private int httpPort;
    private String tunnelServer;
    private String agentId;
    private String appName;
    private String statUrl;
}
  • ConditionalOnProperty通过读取SpringBoot配置文件的指定参数判断是否启用组件,如果判断为False,ArthasConfiguration里的Bean就不会被加载到容器中,即组件的开关。Arthas读取spring.arthas.enabled来判断是否加载组件。如果你想默认启动,没有开关,则可以不指定ConditionalOnProperty。

三.编写自己的Starter

我们写个简单的Starter,不加载配置文件,并且默认启动的Starter。IDE用的是是IDEA社区版。

3.1创建一个SpringBootStarter项目

3.1.1 新建项目,选择使用Maven构建。

SpringBoot Starter缘起

3.1.2 然后创建spring.factories文件和配置类。

SpringBoot Starter缘起

3.1.3 spring.factories写入配置类的全称。

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.bjgoodwil.SpringBootStarterConfiguration

3.1.4 Maven打包

使用Maven的site命令打包jar到自己的本地仓库中。

3.2在SpringBoot项目中引入jar

打开一个SpringBoot项目,在pom文件中引入Jar(直接拷贝Starter pom文件中的参数),启动SpringBoot项目,控制台就会打印配置类的打印语句。

<!--自定义Starter-->
<dependency>
    <groupId>com.bjgoodwill</groupId>
    <artifactId>springbootstarter</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>