最简单的答案是遵循spring子项目(引导,数据…)如何实现这种要求。他们通常定义一个自定义的合成批注,以启用该功能并定义一组要扫描的程序包。
例如,给出以下注释:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import({MyInterfaceScanRegistrar.class})
public @interface MyInterfaceScan {
String[] value() default {};
}
在哪里value
定义要扫描的软件包并@Import
启用MyInterfaceScan
检测。
然后创建ImportBeanDefinitionRegistrar
。此类将能够创建bean定义
由在处理@Configuration类时注册其他bean定义的类型所实现的接口。在bean定义级别(与@Bean方法/实例级别相对)进行操作时很有用,这是必需的或必需的。
public class MyInterfaceScanRegistrar implements ImportBeanDeFinitionRegistrar, EnvironmentAware {
private Environment environment;
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}
@Override
public void registerBeanDeFinitions(AnnotationMetadata Metadata, BeanDeFinitionRegistry registry) {
// Get the MyInterfaceScan annotation attributes
Map<String, Object> annotationAttributes = Metadata.getAnnotationAttributes(MyInterfaceScan.class.getCanonicalName());
if (annotationAttributes != null) {
String[] basePackages = (String[]) annotationAttributes.get("value");
if (basePackages.length == 0){
// If value attribute is not set, fallback to the package of the annotated class
basePackages = new String[]{((StandardAnnotationMetadata) Metadata).getIntrospectedClass().getPackage().getName()};
}
// using these packages, scan for interface annotated with MyCustomBean
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false, environment){
// Override isCandidateComponent to only scan for interface
@Override
protected boolean isCandidateComponent(AnnotatedBeanDeFinition beanDeFinition) {
AnnotationMetadata Metadata = beanDeFinition.getMetadata();
return Metadata.isIndependent() && Metadata.isInterface();
}
};
provider.addIncludeFilter(new AnnotationTypeFilter(MyCustomBean.class));
// Scan all packages
for (String basePackage : basePackages) {
for (BeanDeFinition beanDeFinition : provider.findCandidateComponents(basePackage)) {
// Do the stuff about the bean deFinition
// For example, redefine it as a bean factory with custom atribute...
// then register it
registry.registerBeanDeFinition(generateAName() , beanDeFinition);
System.out.println(beanDeFinition);
}
}
}
}
}
这是逻辑的核心。可以将Bean定义作为具有属性的Bean工厂进行操作和重新定义,也可以使用从接口生成的类重新定义。
MyCustomBean
是一个简单的注释:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyCustomBean {
}
可以注释接口:
@MyCustomBean
public interface Class1 {
}
提取软件包定义的代码@ComponentScan
将更加复杂。
您应该创建一个BeanDefinitionRegistryPostProcessor并模仿ConfigurationClassPostProcessor:
遍历bean注册表以使用具有ComponentScan
属性的声明类(例如从中提取ConfigurationClassPostProcessor
)来定义bean :
public void postProcessBeanDeFinitionRegistry(BeanDeFinitionRegistry registry) {
List
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);