@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?
发布于 2018-06-12 14:32:21
为了您自己的目的而重用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作为默认值。
https://stackoverflow.com/questions/50808941
复制相似问题