Files
tushare-data-service/src/main/java/link/at17/mid/tushare/component/ConfigAutoRegistrar.java
2025-10-14 15:12:24 +08:00

74 lines
3.9 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package link.at17.mid.tushare.component;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.DependsOn;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.core.type.filter.AssignableTypeFilter;
import link.at17.mid.tushare.annotation.ConfigInfo;
import link.at17.mid.tushare.interfaces.IConfig;
import lombok.extern.slf4j.Slf4j;
/**
* 实现自动化注册 Config
*/
@Slf4j
@DependsOn("configService")
public class ConfigAutoRegistrar implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
scanner.addIncludeFilter(new AssignableTypeFilter(IConfig.class));
scanner.addIncludeFilter(new AnnotationTypeFilter(ConfigInfo.class));
scanner.findCandidateComponents("link.at17.mid.tushare.system.config").forEach(beanDefinition -> {
String className = beanDefinition.getBeanClassName();
try {
// 确保其 field 规则与 configService 内 field 生成规则一致,即:
// 如果 @ConfigInfo 指定了 field 的,使用该 field + "Config"
// 作为 beanName否则使用首字母小写的 simpleClassName 作为
// beanName且 simpleClassName 无论如何必须以 Config 作为结尾。
Class<?> clazz = Class.forName(className);
String beanName = clazz.getSimpleName().substring(0, 1).toLowerCase()
+ clazz.getSimpleName().substring(1);
if (!IConfig.class.isAssignableFrom(clazz)) {
log.warn("Config {} does not implement IConfig, ignore", beanName);
return;
}
if (!beanName.endsWith("Config")) {
log.warn("Config {}'s simple class name does not end with \"Config\", ignore", beanName);
return;
}
ConfigInfo info = clazz.getAnnotation(ConfigInfo.class);
if (info == null) {
log.warn("Config {} does not have @ConfigInfo annotation, ignore", clazz.getName());
return;
}
if (StringUtils.isNotBlank(info.field())) {
beanName = info.field() + "Config";
}
BeanDefinitionBuilder factoryBean = BeanDefinitionBuilder
.genericBeanDefinition(ConfigServiceFactoryBean.class)
.addConstructorArgValue(clazz);
// 注意此处注册 factoryBean 不意味着 FactoryBean.getObject() 方法立即被执行,
// Spring 管理的 Bean 默认在其被使用时才创建,所以如果 getObject() 调用一些方
// 法,这些方法会在初次使用 Bean 时才被创建。如果这些方法对于启动过程很重要,
// 需要在对应 Config(Bean) 上加上 @Bean 和 @Lazy(false) 注解,确保一旦准备好
// 相应的 Bean 就会被创建。
registry.registerBeanDefinition(beanName, factoryBean.getBeanDefinition());
log.info("Add config {} to bean register", beanName);
} catch (ClassNotFoundException e) {
throw new RuntimeException("Failed to load class: " + className, e);
}
});
}
}