springboot项目创建笔记26 之《自定义starter包》

springboot中如果需要引入某个功能,只要引入它的starter包,就能自动加载它所有的依赖包和配置,非常方便。我们可以自己制作starter包,作为一个组件,给其他系统引用。

1、命名规则
官方starter包:spring-boot-starter-{模块名}
第三方starter包:{模块名}-spring-boot-starter

2、starter包用到了springboot自动装配功能
参考druid-spring-boot-starter-1.1.21.jar,建立一个starter的maven项目:sms-spring-boot-starter

3、制作starter包,有两种方式
方式一:像druid一样全部写在一起,编译出一个jar包
方式二:像pagehelper-spring-boot-starter一样,建立maven多模块项目

<modules>
    <module>pagehelper-spring-boot-autoconfigure</module>
    <module>pagehelper-spring-boot-starter</module>
    <module>pagehelper-spring-boot-samples</module>
</modules>

这里作为演示,所以都写在一个模块里

4、建立pom.xml文件

<?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>
	<groupId>com.example</groupId>
	<artifactId>sms-spring-boot-starter</artifactId>
	<version>1.0.0</version>
	<packaging>jar</packaging>
	<name>sms-spring-boot-starter</name>
	<description>send sms</description>

	<properties>
		<spring-boot.version>2.1.8.RELEASE</spring-boot.version>
	</properties>

	<dependencyManagement>
		<dependencies>
			<!-- 引入springframework依赖包版本 -->
			<dependency>
				<!-- Import dependency management from Spring Boot,not include plugin 
					management as the parent import style -->
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-dependencies</artifactId>
				<version>${spring-boot.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<dependencies>
		<!-- Compile dependencies -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-autoconfigure</artifactId>
		</dependency>

		<!-- Optional dependencies -->
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-lang3</artifactId>
		</dependency>

		<!-- @ConfigurationProperties annotation processing (metadata for IDEs) -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-configuration-processor</artifactId>
			<optional>true</optional>
		</dependency>
	</dependencies>
</project>

说明:
spring-boot-autoconfigure:作用是实现自动装配功能
spring-boot-configuration-processor:作用是编译时生成spring-configuration-metadata.json,此文件是给IDE提示信息使用

5、在/src/main/java下建立包com.example.sms
创建MyMessage.java

package com.example.sms;

/**
 * 模拟发送短信功能
 * @author user
 *
 */
public class MyMessage {

	public void send(String phone, String msg) {
		System.out.println("send to: " + phone + ", msg: " + msg);
	}
}

创建SmsAutoConfiguration.java

package com.example.sms;

import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableConfigurationProperties(SmsProperties.class)
public class SmsAutoConfiguration {
	
	@Bean
	public MyMessage myMessage() {
		return new MyMessage();
	}
}

创建SmsProperties.java

package com.example.sms;

import java.util.Properties;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "sms.properties")
public class SmsProperties {
	
	private Properties properties = new Properties();

	/**
	 * 超时时间
	 */
	private String timeout;
	
	/**
	 * 重试次数
	 */
	private String retry;

	public String getTimeout() {
		return properties.getProperty("timeout");
	}

	public void setTimeout(String timeout) {
		properties.setProperty("timeout", timeout);
	}

	public String getRetry() {
		return properties.getProperty("retry");
	}

	public void setRetry(String retry) {
		properties.setProperty("retry", retry);
	}
	
}

实现作用:
SmsAutoConfiguration类创建MyMessage对象和SmsProperties对象
SmsProperties类加载配置文件中的配置项

6、注解说明
@ConfigurationProperties:自定义属性配置类
@EnableConfigurationProperties:使@ConfigurationProperties注解的类生效,并且将该类注入到IOC容器中,交由IOC容器进行管理
@ConditionalOnBean:spring容器中存在指定class的实例对象时,对应的配置才生效
@ConditionalOnClass:classpath中存在指定class时的实例对象时,对应的配置才生效
@Import:把类的实例加入spring的IOC容器中
@AutoConfigureBefore:在指定的Configuration类之前加载
@AutoConfigureAfter:在指定的Configuration类之后加载

7、在src/main/resources下建立文件夹META-INF,在META-INF下建立spring.factories

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.sms.SmsAutoConfiguration

8、引用sms-spring-boot-starter包
另一个项目pom文件,添加依赖:

<!-- 自定义starter包 -->
<dependency>
	<groupId>com.example</groupId>
	<artifactId>sms-spring-boot-starter</artifactId>
	<version>1.0.0</version>
</dependency>

添加测试类StarterTest.java:

package myboot;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import com.example.myboot.MybootApplication;
import com.example.sms.MyMessage;
import com.example.sms.SmsProperties;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = MybootApplication.class)
public class StarterTest {

	@Autowired
	MyMessage myMessage;
	
	@Autowired
	SmsProperties smsProperties;
	
	@Test
	public void testSend() {
		System.out.println("timeout is: " + smsProperties.getTimeout());
		System.out.println("retry is: " + smsProperties.getRetry());
		myMessage.send("13600000001", "你好");
	}
}

执行结果:

timeout is: 1000
retry is: 6
send to: 13600000001, msg: 你好

引入的starter包的目录结构:

加载流程
springboot启动 --> 通过spring.factories加载xxxAutoConfiguration类 --> 内部加载xxxProperties类获取配置文件中的属性,或者创建bean

参考资料:
https://cloud.tencent.com/developer/article/1415098
https://www.cnblogs.com/zhoading/p/12194960.html
http://www.hyhblog.cn/2018/08/29/spring-boot-unable-to-read-meta-data-for-class/
 

Guess you like

Origin blog.csdn.net/csj50/article/details/120135120