自定义spring boot starter

 
 

0. 写在前面

这部分内容将会简要介绍如何定制自己的starter,以及starter的一些基本原理

1. starter的pom文件配置

starter本身也是作为一个spring boot的应用,因此需要引入parent,同时引入基本的starter

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

为了给可配置的bean属性生成元数据,我们需要引入如下jar包

<!--将被@ConfigurationProperties注解的类的属性注入到元数据-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>

生成的元数据位于jar文件中的META-INF/spring-configurationmetadata. json。元数据本身并不会修改被@ConfigurationProperties修饰的类属性,在我的理解里元数据仅仅只是表示配置类的默认值以及java doc,供调用者便利的了解默认配置有哪些以及默认配置的含义,在idea里面如果有元数据则可以提供良好的代码提示功能以方便了解默认的配置。
自定义的starter的配置类如下:

@ConfigurationProperties(prefix = QssProperties.PROP_PREFIX)
public class QssProperties {
    public static final String PROP_PREFIX = "qss";

    /**
     * qss en name
     */
    private String name;

    private Integer age = 27;

    @NestedConfigurationProperty
    private BasicProperties basicProperties;

    public String getName() {
        return name;
    }

    public QssProperties setName(String name) {
        this.name = name;
        return this;
    }

    public Integer getAge() {
        return age;
    }

    public QssProperties setAge(Integer age) {
        this.age = age;
        return this;
    }

    public BasicProperties getBasicProperties() {
        return basicProperties;
    }

    public QssProperties setBasicProperties(BasicProperties basicProperties) {
        this.basicProperties = basicProperties;
        return this;
    }
}
public class BasicProperties {
    private String basic;

    public String getBasic() {
        return basic;
    }

    public BasicProperties setBasic(String basic) {
        this.basic = basic;
        return this;
    }
}

生成的元数据配置如下:

{
  "hints": [],
  "groups": [
    {
      "sourceType": "com.qss.autoconfigure.QssProperties",
      "name": "qss",
      "type": "com.qss.autoconfigure.QssProperties"
    },
    {
      "sourceType": "com.qss.autoconfigure.QssProperties",
      "name": "qss.basic-properties",
      "sourceMethod": "getBasicProperties()",
      "type": "com.qss.autoconfigure.BasicProperties"
    }
  ],
  "properties": [
    {
      "sourceType": "com.qss.autoconfigure.QssProperties",
      "defaultValue": 27,
      "name": "qss.age",
      "type": "java.lang.Integer"
    },
    {
      "sourceType": "com.qss.autoconfigure.BasicProperties",
      "name": "qss.basic-properties.basic",
      "type": "java.lang.String"
    },
    {
      "sourceType": "com.qss.autoconfigure.QssProperties",
      "name": "qss.name",
      "description": "qss en name",
      "type": "java.lang.String"
    }
  ]
}

group表示元数据的分组,properties表示属性列表,sourceType表示来源类,type表示属性的类型,name表示属性名,defaultValue表示默认值,sourceMethod表示贡献该组属性的方法名,比如这里的getBasicProperties()来获取basicProperties的配置。这里需要注意的是在basicProperties上使用了@NestedConfigurationProperty,该注解会为basicProperties生成单独的一个属性组。如果不添加该注解,则不会生成单独的属性组,而是形成如下的一个属性节点:

{
      "sourceType": "com.qss.autoconfigure.QssProperties",
      "name": "qss.basic-properties",
      "type": "com.qss.autoconfigure.BasicProperties"
    },

2. starter的入口

Spring Boot会检查你发布的jar中是否存在 META-INF/spring.factories 文件,
该文件中以 EnableAutoConfiguration 为key的属性应该列出你的配置类

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.mycorp.libx.autoconfigure.LibXAutoConfiguration,\
com.mycorp.libx.autoconfigure.LibXWebAutoConfiguration

我们可以使用 @AutoConfigureAfter@AutoConfigureBefore或者@Order 注解为配置类指定特定的顺序,在demo中我使用的配置是:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.qss.autoconfigure.QssStarterConfig

配置类的定义如下,首先需要使用@Configuration,通过@EnableConfigurationProperties可以将被@ConfigurationProperties注解的类生成一个bean。再来看QssService这个bean的配置,我们可以通过一系列@Condition*注解来表示bean的生成条件,这里使用了@ConditionalOnClass({QssService.class}),@ConditionalOnMissingBean({QssService.class})表示生成这个bean需要保证类路径下QssProperties.class这个类并且该bean不存在于spring的上下文。注意@ConditionalOnBean并不保证bean的加载顺序,spring boot只是通过扫描判断是否会生成该bean

@Configuration
@EnableConfigurationProperties({QssProperties.class})
public class QssStarterConfig {

    @Autowired
    private QssProperties qssProperties;

    @Bean
    @ConditionalOnClass({QssService.class})
    @ConditionalOnMissingBean({QssService.class})
    public QssService getQssService(){
        return new QssService().setProperties(qssProperties);
    }
}

一些其他的条件注解如下:

@ConditionalOnWebApplication : web环境
@ConditionalOnNotWebApplication : 条件是当前不是web应用
@ConditionalOnProperty : 检查特定属性是否已经配置了特定值
@ConditionalOnResource : 检查特定的资源是否已经在类路径下
@ConditionalOnMissingClass : 不包含某个类
@ConditionalOnSingleCandidate: 表示只能有一个候选bean,如果超过一个,可以使用@Primary指定首选,这样才不会抛出异常

3. bean类的编写

这里只使用了一个简单的bean,当其他项目引入该starter时,qssService这个bean已经可以直接依赖注入到项目中其他类。

public class QssService {

    private QssProperties properties;

    public QssService setProperties(QssProperties properties) {
        this.properties = properties;
        return this;
    }

    public String sayHello(){
        return JSON.toJSONString(properties);
    }
}


作者:ImushroomT
链接:https://www.jianshu.com/p/547fe62365f8
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值