该文章只为了记录一些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;
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;
@Configuration @Import(ImportSelectorImpl.class) public class AutoImportConfig { }
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博客