Starter

实现自定义的spring-boot-starter

https://docs.spring.io/spring-boot/docs/2.0.1.RELEASE/reference/html/boot-features-developing-auto-configuration.html

1. 目录结构

starter[项目名称]
    -- src
        -- main
            -- java
                -- package [项目包名]
                    -- EnableXXX.java
                    -- XXXMarkerConfiguration.java
                    -- XXXAutoConfiguration.java
                    -- XXXProperties.java
                    -- XXXService.java
            -- resources
                -- META-INF
                    -- additional-spring-configuration-metadata.json [application.properties/yml 自动提示]
                    -- spring.factories
        -- test
            -- java
            -- resources

2. 依赖导入

使用maven或者gradle配置项目

使用gradle配置项目时build.gradle实现


buildscript {
    ext {
        springBootVersion = '2.0.1.RELEASE'
    }
    repositories {
        maven { url "http://maven.aliyun.com/nexus/content/groups/public/" }
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'io.spring.dependency-management'

// 配置编码
compileJava.options.encoding = 'UTF-8'
// 配置java编译版本
sourceCompatibility = 1.8
targetCompatibility = 1.8

// 配置maven仓库
repositories {
    maven { url "http://maven.aliyun.com/nexus/content/groups/public/" }
}

// 配置依赖
dependencies {
    compile "org.springframework.boot:spring-boot-autoconfigure:2.0.1.RELEASE"
    compile "org.springframework.boot:spring-boot-configuration-processor:2.0.1.RELEASE"
}

compileJava.dependsOn(processResources)

3. 代码实现

3.1 Enable形式实现自动加载

自定义注解, 启用配置项, 使用import导入配置类

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(XXXMarkerConfiguration.class)
public @interface EnableXXX {
}
@Configuration
public class XXXMarkerConfiguration {

    @Bean
    public Marker markerBean() {
        return new Marker();
    }

    class Marker {
    }
}

重要: 通过@ConditionalOnBean(XXXMarkerConfiguration.Marker.class)配置, 程序在Application时配置 Enable注解后,自动加载自定义配置

@Configuration
@ConditionalOnBean(XXXMarkerConfiguration.Marker.class)
@EnableConfigurationProperties(XXXProperties.class)
public class XXXAutoConfiguration {

}

3.2 配置自定义属性

@Component
@ConfigurationProperties(prefix = "prefix")
public class XXXProperties {
    // 属性key
    private String key;

    // 省略setter/getter方法
    ...
}

XXXService服务

@Component
public class XXXService {

    @Autowired                     
    private XXXProperties properties;

    public String test(){
        return properties.getKey();
    }
}

AutoConfiguration中配置自定义的Bean, 提供外部依赖使用

public class XXXAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean(XXXService.class)
    public XXXService xxxService(){
        return new XXXService();
    }
}

3.3 配置资源依赖文件

META-INF目录下spring.factories这个properties文件中, 配置key为org.springframework.boot.autoconfigure.EnableAutoConfiguration,这样才会被springboot自动加载


# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=package.XXXAutoConfiguration

配置属性文件自动提示, 通过添加additional-spring-configuration-metadata.json文件实现

https://docs.spring.io/spring-boot/docs/2.0.1.RELEASE/reference/html/configuration-metadata.html#configuration-metadata-annotation-processor

{
  "properties": [
    {
      "name": "prefix.key",
      "type": "java.lang.String",
      "sourceType": "package.XXXProperties",
      "description": "key.",
      "defaultValue": "default"
    }
  ],
  "hints": [
  ]
}

4. 示例

引入相关依赖

   <dependency>
       <groupId>xxxx</groupId>
       <artifactId>xxx-spring-boot-starter</artifactId>
       <version>xxx</version>
   </dependency>
dependencies {
    compile 'groupId:xxx-spring-boot-starter:xxx'
}

自动配置服务

@SpringBootApplication
@EnableXXX
public class Application {

    @Autowired
    private XXXService xxxService;

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

5.注解说明

注解 说明
@ConditionalOnBean 当容器中有指定的Bean的条件下
@ConditionalOnClass 当类路径下有指定的类的条件下
@ConditionalOnExpression 基于SpEL表达式作为判断条件
@ConditionalOnJava 基于JVM版本作为判断条件
@ConditionalOnJndi 在JNDI存在的条件下查找指定的位置
@ConditionalOnMissingBean 当容器中没有指定Bean的情况下
@ConditionalOnMissingClass 当类路径下没有指定的类的条件下
@ConditionalOnNotWebApplication 当前项目不是Web项目的条件下
@ConditionalOnProperty 指定的属性是否有指定的值
@ConditionalOnResource 类路径下是否有指定的资源
@ConditionalOnSingleCandidate 当指定的Bean在容器中只有一个,或者在有多个Bean的情况下,用来指定首选的Bean
@ConditionalOnWebApplication 当前项目是Web项目的条件下

results matching ""

    No results matching ""