摘要
该文章只为了记录一些Spring的使用,比如自建starter、配置属性提示、自动注册Bean等操作
正文
该文章只为了记录一些Spring的使用,比如自建starter、配置属性提示、自动注册Bean等操作
本文涉及到的源码
一、starter添加属性提示
首先,建个配置类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
| @ConfigurationProperties(prefix = "person")
public class PersonProperties {
/**
* 姓名
*/
private String name = "尸祖降臣";
/**
* 身价
*/
private Double money = 1.0;
/**
* 生日
*/
private String birth = "1970-01-01 00:00:00";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getMoney() {
return money;
}
public void setMoney(Double money) {
this.money = money;
}
public String getBirth() {
return birth;
}
public void setBirth(String birth) {
this.birth = birth;
}
}
|
其次,添加依赖
1
2
3
4
5
6
7
| <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>2.5.4</version>
<optional>true</optional>
<scope>provided</scope>
</dependency>
|
引用该starter,会发现已有提示。
二、starter自动注册Bean
自动注册Bean,我目前使用到了两种方式
- spring.factories
- 适用于bean较少的情况,指定自建配置类,进行bean的自动注册
- import
2.1 spring.factories
示例配置类
1
2
3
4
5
6
7
8
9
10
11
12
13
| @Configuration
@ConditionalOnClass(Log.class)
public class LogAutoConfiguration {
private final Logger log = LoggerFactory.getLogger(LogAutoConfiguration.class);
@Bean
public LogHandler logHandler() {
LogHandler logHandler = new LogHandler();
log.debug("自动装配bean--日志切面处理器");
return logHandler;
}
}
|
配置spring.factories
将spring.factories放置到路径resources/META-INF下
1
| org.springframework.boot.autoconfigure.EnableAutoConfiguration=top.meethigher.log.LogAutoConfiguration
|
2.2 import批量注册bean
首先创建importSelector.properties
1
2
| serviceImplClass=top.meethigher.starter.importbean.impl.TestAImpl,\
top.meethigher.starter.importbean.impl.TestBImpl
|
如果类太多,可以直接使用如下脚本,在junit单元测试环境下,自动生成配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
import org.junit.Test;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.LinkedList;
import java.util.List;
/**
* 生成import Bean配置文件
*
* @author chenchuancheng github.com/meethigher
* @since 2023/6/5 00:35
*/
public class GenerateImportProperties {
private final static String serviceImplPath;
static {
String serviceImplRoot = "/target/classes/top/meethigher/starter/importbean/impl";
String root = System.getProperty("user.dir").replace("\\", "/");
serviceImplPath = root + serviceImplRoot;
}
@Test
public void generateImportProperties() throws Exception {
String serviceImplPackageName = "top.meethigher.starter.importbean.impl";
String serviceImplClazz = "serviceImplClass=";
List<Class<?>> serviceImplClasses = walkDir(serviceImplPath, serviceImplPackageName);
StringBuilder sb = new StringBuilder();
sb.append(generateConfig(serviceImplClazz, serviceImplClasses));
System.out.println(sb.toString());
}
private List<Class<?>> walkDir(String root, String packageName) throws Exception {
List<Class<?>> list = new LinkedList<>();
try (DirectoryStream<Path> stream = Files.newDirectoryStream(Paths.get(root), "*.class")) {
for (Path path : stream) {
String className = packageName + "." + path.getFileName().toString().replace(".class", "");
Class<?> clazz = Class.forName(className);
list.add(clazz);
}
}
return list;
}
private String generateConfig(String prefix, List<Class<?>> classes) throws Exception {
StringBuilder sb = new StringBuilder();
sb.append(prefix);
for (int i = 0; i < classes.size(); i++) {
Class<?> clazz = classes.get(i);
if (i == classes.size() - 1) {
sb.append(clazz.getName())
.append("\n");
} else {
sb.append(clazz.getName())
.append(",")
.append("\\")
.append("\n");
}
}
sb.append("\n");
return sb.toString();
}
}
|
核心就在于@Import注解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
| import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
import java.util.ResourceBundle;
import java.util.function.Predicate;
/**
* 配合spring.factories实现自动装配
*
* @author chenchuancheng github.com/meethigher
* @since 2023/6/5 00:49
*/
@Configuration
@Import(ImportSelectorImpl.class)
public class AutoImportConfig {
}
/**
* 导入
*
* @author chenchuancheng github.com/meethigher
* @since 2023/6/5 00:45
*/
class ImportSelectorImpl implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
ResourceBundle rb = ResourceBundle.getBundle("importSelector");
String serviceImplItems = rb.getString("serviceImplClass");
String[] serviceImplArr = serviceImplItems.split(",");
return serviceImplArr;
}
public String[] mergeArrays(String[] arr1, String[] arr2, String[] arr3) {
String[] result = new String[arr1.length + arr2.length + arr3.length];
System.arraycopy(arr1, 0, result, 0, arr1.length);
System.arraycopy(arr2, 0, result, arr1.length, arr2.length);
System.arraycopy(arr3, 0, result, arr1.length + arr2.length, arr3.length);
return result;
}
@Override
public Predicate<String> getExclusionFilter() {
return ImportSelector.super.getExclusionFilter();
}
}
|
引用该starter,会发现已批量自动注册bean
三、参考致谢
Spring系列之@import详解(bean批量注册)_spring @import_azhou的代码园的博客-CSDN博客
Spring boot starter 如何给配置添加idea 提示功能 spring-boot-configuration-processor_自定义starter让idea配置提示_Young丶的博客-CSDN博客