虽说springboot已经帮我们把很多东西都配置好了,但不排除某些场景下还是要自己做一个starter

因为没有业务需求,所以做的非常简单,仅看效果,新建一个项目

常用条件注解

springboot提供了很多条件注解用来判断是否注入此bean对象,避免启动报错

@ConditionalOnProperty 用来配置starter配置类生效的条件
@ConditionalOnMissingBean 用来配置Bean不生效的条件,比如存在某个名字的bean时不生效
@ConditionalOnBean 配置Bean生效的条件,与ConditionalOnMissingBean相反

简单过一遍

maven依赖

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter</artifactId>
  4. <scope>provided</scope>
  5. <optional>true</optional>
  6. </dependency>
  7. <!-- 集成spring-boot,配置文件属性处理依赖 -->
  8. <dependency>
  9. <groupId>org.springframework.boot</groupId>
  10. <artifactId>spring-boot-configuration-processor</artifactId>
  11. <scope>provided</scope>
  12. <optional>true</optional>
  13. </dependency>

写一个自定义的自动配置类,内容非常简单

首先这个类得是一个配置类,所以要用到@Configuration

@ConditionalOnProperty 注解表示该自动配置类生效的条件是需要在springboot配置文件中写入这个配置,如果不使用此注解,就表示该类生效不需要前置条件了,直接导入依赖就可以生效

@Configuration
@ConditionalOnProperty(name = "enabled.autoConfiguration.my_starter")
public class MyStarterAutoConfiguration {

    static {
        System.out.println("..........my starter............");
        System.out.println("..........my starter............");
        System.out.println("..........my starter............");
    }

}

如果该类自动配置成功,那么控制台就会输出这三句

spring.factories文件

可以说是starter的核心,类似spi思想,在resources目录下创建META-INF目录然后创建一个名为spring.factories的文件
image.png
文件内容类似.properties的文件,自动配置类在=号前面必须这么写,下面则是我的自动配置类的全路径,springboot项目启动时会根据依赖扫描所有spring.factories文件实现自动装配

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.halayang.MyStarterAutoConfiguration

starter项目写完了,接下来在springboot项目里直接用就行了

springboot项目

回到springboot项目中,先导入此starter项目依赖,又因为我设置了生效的前提条件,所以需要在application.yml配置文件中做一下配置

enabled:
  autoConfiguration:
    my_starter: true

现在可以启动springboot项目了
image.png

出现了这三行,starter自定义成功

更多操作

一般在配置文件中设置的东西会比较多
自定义一个ConfigurationProperties配置类,这样配置文件中以global为前缀的配置项就是配置此的,Email和Sms是自定义对象,可以通过配置文件直接给属性赋值

@ConfigurationProperties(prefix = GlobalProperties.GLOBAL_PREFIX)
public class GlobalProperties {

    public static final String GLOBAL_PREFIX = "global";

    private boolean enabled;

    private Email email;

    private Sms sms;

    public GlobalProperties(Email email, Sms sms) {
        this.email = email;
        this.sms = sms;
    }

    public boolean isEnabled() {
        return enabled;
    }

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    public Email getEmail() {
        return email;
    }

    public void setEmail(Email email) {
        this.email = email;
    }

    public Sms getSms() {
        return sms;
    }

    public void setSms(Sms sms) {
        this.sms = sms;
    }
}

Starter配置类

global.enabled为true时此配置类才生效
此配置类生成两个bean对象,如果调用者存在同名的bean就不生效,没有配置也不生效

@Configuration
@EnableConfigurationProperties(GlobalProperties.class)
@ConditionalOnProperty(prefix = GlobalProperties.GLOBAL_PREFIX, name = "enabled", havingValue = "true", matchIfMissing = true)
public class GlobalConfig {

    private final GlobalProperties globalProperties;

    public GlobalConfig(GlobalProperties globalProperties) {
        this.globalProperties = globalProperties;
    }

    @Bean("emailService")
    @ConditionalOnMissingBean(name = "emailService")
    @ConditionalOnProperty(prefix = GlobalProperties.GLOBAL_PREFIX, name = "email.enabled", havingValue = "true", matchIfMissing = true)
    public EmailService emailService() {
        return new EmailService(globalProperties.getEmail());
    }

    @Bean("smsService")
    @ConditionalOnMissingBean(name = "smsService")
    @ConditionalOnProperty(prefix = GlobalProperties.GLOBAL_PREFIX, name = "sms.enabled", havingValue = "true", matchIfMissing = true)
    public SmsService smsService() {
        return new SmsService(globalProperties.getSms());
    }

}

同理,要注意META-INF目录下的spring.factories文件的配置