@SpringBootApplication
的scanBasePackages配置如下:
package com.xxx.boot.sample;
@SpringBootApplication(scanBasePackages = { "com.xxx.boot.sample", "com.xxx.boot.service" })
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
要求是我们希望通过在运行时编程零属性配置而不是通过注释来集成Apache Dubbo组件注释扫描与Spring Boot。
@Configuration
@ConditionalOnClass({ EnableDubboConfig.class, AbstractConfig.class })
@ConditionalOnProperty(prefix = "dubbo", name = "enabled", havingValue = "true", matchIfMissing = true)
public class DubboAutoConfiguration {
/// Dubbo配置
@Configuration
@EnableDubboConfig
@ConditionalOnProperty(prefix = "dubbo.config", name = "enabled", havingValue = "true", matchIfMissing = true)
@EnableConfigurationProperties(DubboProperties.class)
public static class DubboConfigConfiguration {
}
/// Dubbo注解扫描
@Configuration
@ConditionalOnClass({ Service.class, Reference.class })
@ConditionalOnProperty(prefix = "dubbo.annotation", name = "enabled", havingValue = "true", matchIfMissing = true)
public static class DubboAnnotationConfiguration {
@Bean(name = "serviceAnnotationBeanPostProcessor")
@ConditionalOnMissingBean
public ServiceAnnotationBeanPostProcessor serviceAnnotationBeanPostProcessor(BeanFactory beanFactory) {
// 获取 Spring Boot 主入口类所在的包路径
List<String> packagesToScan = AutoConfigurationPackages.get(beanFactory);
if (packagesToScan == null) {
packagesToScan = Collections.emptyList();
}
return new ServiceAnnotationBeanPostProcessor(packagesToScan);
}
@Bean(name = ReferenceAnnotationBeanPostProcessor.BEAN_NAME)
@ConditionalOnMissingBean
public ReferenceAnnotationBeanPostProcessor referenceAnnotationBeanPostProcessor() {
return new ReferenceAnnotationBeanPostProcessor();
}
}
}
但AutoConfigurationPackages#get(BeanFactory)
仅返回"com.xxx.boot.sample"
,不包括"com.xxx.boot.service"
。我希望返回所有scanBasePackages
值。
通过调试,我发现@SpringBootApplication
实例是一个代理类实例。我尝试使用注释Class#getAnnotations
,然后通过反射获取scanBasePackages字段。但没有成功。
问题:
如何以编程方式获取scanBasePackages of @SpringBootApplication
或basePackages of @ComponentScan
?
答案 0 :(得分:2)
尝试为您自己的目的重复使用scanBasePackages
属性并不可取。如果您查看@SpringBootApplication
的来源,您会看到以下内容:
@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
String[] scanBasePackages() default {};
@AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
Class<?>[] scanBasePackageClasses() default {};
这就是说这些属性是@ComponentScan
的别名。由于此注释可用于任何@Configuration
类,因此拥有其中许多注释实际上是合法的。
@ComponentScan
注释会触发ConfigurationClassParser
的扫描。查看所有血腥细节的doProcessConfigurationClass
方法。
如果您真的想自己找到注释属性,可以执行以下操作:
applicationContext.getBeansWithAnnotation(ComponentScan.class).forEach((name, instance) -> {
Set<ComponentScan> scans = AnnotatedElementUtils.getMergedRepeatableAnnotations(instance.getClass(), ComponentScan.class);
for (ComponentScan scan : scans) {
System.out.println(Arrays.toString(scan.basePackageClasses()));
System.out.println(Arrays.toString(scan.basePackages()));
}
});
这只会让你获得这两个值。您仍未考虑任何@Condition
注释或任何包含/排除过滤器。您也不会处理@ComponentScan()
这意味着从当前包中扫描。
Spring Boot在这些情况下倾向于为特定目的定义新注释。例如,您可以使用@EntityScan
来定义找到JPA实体的位置。然后,如果您未指定任何覆盖,我们将使用AutoConfigurationPackages
作为默认值。