Spring Boot自定义Starter

相信在了解SpringBoot时后已经知道了starter是SpringBoot的核心组成部分,SpringBoot为我们提供了尽可能完善的封装,提供了一系列的自动化配置的starter插件,我们在使用只需要在pom.xml配置文件内添加依赖就可以了,很好的降低了使用框架时的复杂度。那我们如何实现一个自己的starter呢?

1. 知识点回顾

  1. @ConfigurationProperties,该注解可以完成将application.properties配置文件内的有规则的配置参数映射到实体内的field内,不过需要提供setter方法
  2. @Configuration:标识为一个配置类,可以替换xml, 引用了@Component注解表示会被注册的Bean容器中
  3. @EnableConfigurationProperties:这是一个开启使用配置参数的注解,value值就是我们配置实体参数映射的ClassType,将配置实体作为配置来源
  4. @ConditionalOnBean:当SpringIoc容器内存在指定Bean的条件
  5. @ConditionalOnClass:当SpringIoc容器内存在指定Class的条件
  6. @ConditionalOnExpression:基于SpEL表达式作为判断条件
  7. @ConditionalOnJava:基于JVM版本作为判断条件
  8. @ConditionalOnJndi:在JNDI存在时查找指定的位置
  9. @ConditionalOnMissingBean:当SpringIoc容器内不存在指定Bean的条件
  10. @ConditionalOnMissingClass:当SpringIoc容器内不存在指定Class的条件
  11. @ConditionalOnNotWebApplication:当前项目不是Web项目的条件
  12. @ConditionalOnProperty:指定的属性是否有指定的值
  13. @ConditionalOnResource:类路径是否有指定的值
  14. @ConditionalOnSingleCandidate:当指定Bean在SpringIoc容器内只有一个,或者虽然有多个但是指定首选的Bean
  15. @ConditionalOnWebApplication:当前项目是Web项目的条件

以上Conditional开头的注解都是内置的条件注解,是元注解@Conditional演变而来的,根据条件判断是否需要创建对应实例。

2. 自定义Starter

官网:Creating Your Own Starter

2.1 模块及命名规范

starter一般都包含两部分:自动配置部分及业务逻辑starter。虽然官方提供的starter都是spring-boot开头,但是自定的不建议这样做。而是xxx-spring-boot-starter这种命名方式,xxx表示自定义的业务。

You may combine the auto-configuration code and the dependency management in a single module if you do not need to separate those two concerns.
You should make sure to provide a proper namespace for your starter. Do not start your module names with spring-boot, even if you use a different Maven groupId. We may offer official support for the thing you auto-configure in the future.
As a rule of thumb, you should name a combined module after the starter. For example, assume that you are creating a starter for “acme” and that you name the auto-configure module acme-spring-boot-autoconfigure and the starter acme-spring-boot-starter. If you only have one module that combines the two, name it acme-spring-boot-starter.

2.2 创建工程

创建一个简单的Maven工程,引入自动配置包。

<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.qqxhb</groupId>
	<artifactId>demo-spring-boot-starter</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>
	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-autoconfigure</artifactId>
			<version>2.1.4.RELEASE</version>
		</dependency>
	</dependencies>
</project>
2.3 创建属性配置实体类
import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties("qqxhb")//指定配置文件前缀
public class DemoProperties {

	private String name = "庆余年";
	
	private String year = "2019";

	public String getName() {
		return name;
	}

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

	public String getYear() {
		return year;
	}

	public void setYear(String year) {
		this.year = year;
	}
	
	
}

在上面代码中,@ConfigurationProperties注解内配置了属性preffix值为‘qqxhb’,该属性配置了读取参数的前缀,根据上面的实体属性对应配置文件内的配置则是qqxhb.name、qqxhb.year,同时指定了默认值,配置文件内不进行配置时则是使用默认值。

2.4 创建业务逻辑类
public class DemoService {

	private DemoProperties demoProperties;

	public DemoProperties getDemoProperties() {
		return demoProperties;
	}

	public void setDemoProperties(DemoProperties demoProperties) {
		this.demoProperties = demoProperties;
	}

	public String getProperties() {
		if (demoProperties == null) {
			return null;
		}
		return demoProperties.getName() + " " + demoProperties.getYear();
	}
}

业务逻辑只是简单的依赖属性配置类,并且提供显示属性值的方法。

2.5 实现自动配置逻辑

自动配置,这一块是starter的核心部分,自动配置提供实体bean的验证以及初始化,配置该部分后在启动项目时才会自动加载配置。

创建自动配置类

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
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;

@Configuration // 标识配置类
@EnableConfigurationProperties(DemoProperties.class) // 开启DemoProperties对象
@ConditionalOnClass(DemoService.class) // 存在DemoService时初始化该配置类
//存在对应配置信息时初始化该配置类
@ConditionalOnProperty(prefix = "qqxhb", // 存在配置前缀qqxhb
		value = "enabled", // 开启
		matchIfMissing = true// 缺失检查
)
public class DemoAutoConfiguration{

	@Autowired
	private DemoProperties demoProperties;

	/**
	 * 根据条件实例化DemoService
	 * 
	 * @return
	 */
	@Bean
	@ConditionalOnMissingBean(DemoService.class) // 缺失DemoService实体bean时,初始化DemoService并添加到SpringIoc
	public DemoService demoService() {
		DemoService demoService = new DemoService();
		demoService.setDemoProperties(demoProperties);
		return demoService;
	}
}

创建自动配置文件META-INF/spring.factories
springboot自动配置原理

在 resources 下创建文件夹 META-INF 并在 META-INF 下创建文件 spring.factories。

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.qqxhb.stater.demo.DemoAutoConfiguration
2.6 测试

先将starter打包install到本地仓库,然后引入测试项目。

<dependency>
			<groupId>com.qqxhb</groupId>
			<artifactId>demo-spring-boot-starter</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>

编写测试类,使用默认配置测试。

@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoStarterTest {

	@Autowired
	DemoService demoService;

	@Test
	public void starterTest() {
		System.out.println(demoService.getProperties());
	}
}

测试通过后,可以在配置文件application.properties中添加配置,再次执行测试代码。

qqxhb.name=爱情公寓第五季
qqxhb.year=2020

到此自定义starter就结束了,相信你已经学会了,期望对你有所帮助。

发布了105 篇原创文章 · 获赞 7 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_43792385/article/details/104388609