疑问
@SpringBootApplication
public class XxxApplication {
public static void main(String []args) {
SpringApplication.run(XxxApplication.class, args);
}
}
为什么按上面的代码写就可以在同包或子包下使用 Component
注解,使得对应的类能被 spring 容器扫描到?
分析
先看 SpringBootApplication
注解:
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
...
}
原来该注解上添加了 ComponentScan
注解,但是没有显示指定 basePackages
的值。
再看 ComponentScanAnnotationParser
类的 parse
方法:
public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, String declaringClass) {
...
Set<String> basePackages = new LinkedHashSet<>();
String[] basePackagesArray = componentScan.getStringArray("basePackages");
for (String pkg : basePackagesArray) {
String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
Collections.addAll(basePackages, tokenized);
}
for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) {
basePackages.add(ClassUtils.getPackageName(clazz));
}
// 如果没显示指定 basePackages,则将 XxxApplication 类的包名添加到扫描路径中
if (basePackages.isEmpty()) {
basePackages.add(ClassUtils.getPackageName(declaringClass));
}
scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
@Override
protected boolean matchClassName(String className) {
return declaringClass.equals(className);
}
});
return scanner.doScan(StringUtils.toStringArray(basePackages));
}
可以看到如果没显示指定 basePackages,则将 XxxApplication 类的包名添加到扫描路径中,从而当前包及其子包都能被扫描到。
网友评论