一、基础知识
1、SpringBoot starter机制
SpringBoot中的starter是一种非常重要的机制,能够抛弃以前繁杂的配置,将其统一集成进starter,应用者只需要在maven中引入starter依赖,SpringBoot就能自动扫描到要加载的信息并启动相应的默认配置。starter让我们摆脱了各种依赖库的处理,需要配置各种信息的困扰。SpringBoot会自动通过classpath路径下的类发现需要的Bean,并注册进IOC容器。SpringBoot提供了针对日常企业应用研发各种场景的spring-boot-starter依赖模块。所有这些依赖模块都遵循着约定成俗的默认配置,并允许我们调整这些配置,即遵循"约定大于配置"的理念。
2、为什么要自定义 starter
在我们的日常开发工作中,经常会有一些独立于业务之外的配置模块,我们经常将其放到一个特定的包下,然后如果另一个工程需要复用这块的功能的时候,需要将代码硬拷贝到另一个工程,重新继承一遍,麻烦至极。如果我们将这些可独立于业务代码之外的功能配置模块封装成一个个starter,复用的时候只需要将其在pom中引用依赖即可SpringBoot完成自动装配。
3、自定义 starter的部分场景
动态数据源
登录模块
基于AOP技术实现日志切面
……
4、自定义 starter的命名规则
SpringBoot提供的starter以spring-boot-starter-xxx的方式命名。官方建议自定义的starter使用xxx-spring-boot-starter命名规则。以区分SpringBoot生态提供的starter。
二、starter的实现方法
1、新建一个工程
命名为demo-spring-boot-starter
下图为工程目录结构:
2、pom依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo-spring-boot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo-spring-boot-starter</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>2.0.0.RELEASE</version>
<optional>true</optional>
</dependency>
</dependencies>
</project>
3、定义一个实体类映射配置信息
@ConfigurationProperties(prefix = "demo")它可以把相同前缀的配置信息通过配置项名称映射成实体类,比如我们这里指定prefix = "demo"这样的,我们就能将以demo为前缀的配置项拿到了。若是这个注解报错,加上@Component应该是可以解决的。
ps:其实这个注解很强大,它不但能映射成String或基本类型的变量。还可以映射为List、Map等数据结构。
package com.example.starter.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 描述:配置信息 实体
* @author chengpan
* @date 2020/9/4 下午3:28
*/
@Component
@ConfigurationProperties(prefix = "demo")
public class DemoProperties {
private String sayWhat;
private String toWho;
public String getSayWhat() {
return sayWhat;
}
public void setSayWhat(String sayWhat) {
this.sayWhat = sayWhat;
}
public String getToWho() {
return toWho;
}
public void setToWho(String toWho) {
this.toWho = toWho;
}
}
4、定义一个Service
package com.example.starter.service;
/**
* 描述:随便定义一个Service
* @author chengpan
* @date 2020/9/4 下午3:30
*/
public class DemoService {
public String sayWhat;
public String toWho;
public DemoService(String sayWhat, String toWho) {
this.sayWhat = sayWhat;
this.toWho = toWho;
}
public String say(){
return this.sayWhat + "!"+toWho;
}
}
5、定义一个配置类
这里将DemoService类定义为一个Bean,交给IOC容器。
@EnableConfigurationProperties注解。该注解是用来开启对3步骤中@ConfigurationProperties注解配置Bean的支持。也就是@EnableConfigurationProperties注解告诉SpringBoot能支持@ConfigurationProperties。
也可以在@ConfigurationProperties注解的类上添加@Configuration或者@Component注解
@ConditionalOnProperty注解控制@Configuration是否生效。简单来说也就是我们可以通过yml配置文件中控制@Configuration注解的配置类是否生效。
package com.example.starter.config;
import com.example.starter.properties.DemoProperties;
import com.example.starter.service.DemoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 描述:配置类
* @author chengpan
* @date 2020/9/4 下午3:34
*/
@Configuration
@EnableConfigurationProperties(DemoProperties.class)
@ConditionalOnProperty(
prefix = "demo",
name = "isopen",
havingValue = "true"
)
public class DemoConfig {
@Autowired
private DemoProperties demoProperties;
@Bean(name = "demo")
public DemoService demoService(){
return new DemoService(demoProperties.getSayWhat(), demoProperties.getToWho());
}
}
6、创建spring.factories
在resources文件夹下,新建META-INF文件夹,然后创建spring.factories文件,如下图:
在该文件中加入如下配置,该配置指定上步骤中定义的配置类为自动装配的配置。
#-------starter自动装配---------
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.example.starter.config.DemoConfig
7、测试
在demo-spring-boot-starter工程中执行mvn clean install,一个自定义的starter就好了。
新建测试工程
引入starter依赖
<dependency>
<groupId>com.example</groupId>
<artifactId>demo-spring-boot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
在配置文件application.properties中配置,如下内容:
demo.isopen=true
demo.say-what="做人倔强一点,万事都能熬过去"
demo.to-who="小仙女"
#编码格式
server.servlet.encoding.force=true
server.servlet.encoding.charset=UTF-8
server.servlet.encoding.enabled=true
server.tomcat.uri-encoding=UTF-8
然后写个测试类。内容如下:
package com.example.demo.controller;
import com.example.starter.service.DemoService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* @author chengpan
* @date 2020/9/9 下午4:10
*/
@RestController
public class DemoController {
@Resource(name = "demo")
private DemoService demoService;
@GetMapping("/say")
public String sayWhat(){
return demoService.say();
}
}
测试,效果如下图: