Spring Boot 自定义Starter实现自动配置

Spring Boot 自定义 Starter

前面的代码中,无论是 Spring Boot 中使用 Web、Test,还是 MyBatis、Dubbo,都是通过导入一个相应的 Starter 依赖,然后由 Spring Boot 自动配置完成的。那么,如果我们自己的某项功能也想通过自动配置的方式应用到 Spring Boot 中,为 Spring Boot 项目提供相应支持,需要怎样实现呢?同样,我们需要定义自己的 Starter。

1. 手写 Starter

1.1 需求

下面我们自定义一个我们自己的 Starter,实现的功能是:为用户提供的字符串添加前辍与后辍,而前辍与后辍定义在 yml 或 properties 配置文件中。例如,用户输入的字符串为 China,application.yml 配置文件中配置的前辍为$$$,后辍为+++,则最终生成的字符串为$$$China+++

1.2 实现

A、创建工程

创建一个 Spring Boot 工程,命名为 wrap-spring-boot-starter,并导入 Configuration Processor 与 Lombok 依赖。

Spring Boot 官方给出的 Starter 工程的命名需要遵循如下规范

  • Spring 官方定义的 Starter 格式为:spring-boot-starter-{name},如 spring-boot-starter-web。
  • 非官方 Starter 命名格式为:{name}-spring-boot-starter,如 dubbo-spring-boot-starter。

在这里插入图片描述

在这里插入图片描述

导入的配置处理器依赖为:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-configuration-processor</artifactId>
	<optional>true</optional>
</dependency>

配置以后,在用@ConfigurationProperties的时候,如果配置类写好了成员属性,在配置文件里面会有友好提示。

B、 定义一个 Service 类

该 Service 类是当前 Starter 功能的核心类。其核心功能就是在这个类中完成的。该类中的成员变量可以随意命名,但一般与欲在 Spring Boot 中使用的属性名同名。

@AllArgsConstructor
public class WrapService {
    
    
    private String before;
    private String after;

    // 核心业务方法
    public String wrap(String word) {
    
    
        return before + word + after;
    }
}

C、 定义配置属性封装类

我们指定当前类用于封装来自于 Spring Boot 核心配置文件中的以 wrap.service 开头的 prefix 与 suffix 属性值。即用于封装配置文件中的如下属性值:

  • wrap.service.prefix
  • wrap.service.suffix

该类的对象是由系统自动创建,所以无需将其将给 Spring 容器管理。

// 要读取配置文件中wrap.service.prefix  与  wrap.service.suffix 两个属性的值
@Data
@ConfigurationProperties("wrap.service")
public class WrapServiceProperties {
    
    
    private String prefix;
    private String suffix;
}

D、定义自动配置类

为了加深对“自动配置类与配置文件属性关系”的理解,这里再增加一个功能:为wrap.service 再增加一个组装开关,一个 boolean 属性 enable,当 enable 属性值为 true 时,或没有设置 some.service.enable 属性时才进行组装,若 enable 为 false,则不进行组装。

/**
 * 所谓自动配置,就是配置核心业务实例,或者说,是创建核心业务实例
 */
@Configuration
@ConditionalOnClass(WrapService.class)
@EnableConfigurationProperties(WrapServiceProperties.class)
public class WrapServiceAutoConfiguration {
    
    
    @Autowired
    private WrapServiceProperties properties;

    @Bean
    @ConditionalOnProperty(name = "wrap.service.enable", havingValue = "true", matchIfMissing = true)
    // havingValue = "true" 表示如果wrap.service.enable值为true则条件成立
    // 如果没有配havingValue的值,那么只要值不为"false",都认为条件成立!
    // matchIfMissing 表示如果没有对应配置,那么默认是条件成立还是不成立
    public WrapService wrapService() {
    
    
        return new WrapService(properties.getPrefix(), properties.getSuffix());
    }
	
	// 注意在@Configuration的类中@Bean的创建是有顺序的
	// 下面这个放到上面那么容器中就会有两个WrapService 实例
    @Bean
    @ConditionalOnMissingBean  //容器中没有实例才会创建
    public WrapService wrapService2() {
    
    
        return new WrapService("", "");
    }
}

E、 创建 spring.factories 文件

在 resources/META-INF 目录下创建一个名为 spring.factories 的文件。该配置文件是一个键值对文件,键是固定的,为 EnableAutoConfiguration 类的全限定性类名,而值则为我们自定义的自动配置类。

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.abc.config.WrapServiceAutoConfiguration

2. 使用自定义的 Starter

在本地要使用我们自定义的 Starter,首先要保证其已经被 Install 到了本地 Maven 库。
(1) 创建工程
创建一个 Spring Boot 工程,仅需要一个 web 依赖。
在这里插入图片描述

(2) 导入自定义 Starter 依赖

<dependency>
    <groupId>com.abc</groupId>
    <artifactId>wraper-spring-boot-starter</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>

(3) 定义 properties.yml
自定义 Starter 中的属性在配置文件中也是有自动提示功能的。

wrap:
  service:
    enable: true   # 开关
    prefix: AAA-
    suffix: -BBB

(4) 定义 Controller

@RestController
public class WrapController {
    
    
    @Autowired
    private WrapService service;

    @RequestMapping("/wrap/{param}")
    public String wrapHandler(@PathVariable("param") String param) {
    
    
        return service.wrap(param);
    }
}

(5) 运行访问
启动类无需修改,直接启动运行即可。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_41947378/article/details/108719520