First commit

This commit is contained in:
2025-10-14 15:12:24 +08:00
commit 4bf21639c1
370 changed files with 93952 additions and 0 deletions

View File

@@ -0,0 +1,74 @@
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);
}
});
}
}