Spring学习之@CompnentScan
文章目录
注解说明
@ComponentScan 注解是Spring 提供的对组件进行扫描的注解指令,通常与 @Configuration 注解一起使用,支持在类上重复标注

注解能做什么?
此注解支持以下重要特性:
- 自定义扫描的包范围
- 配置包含扫描组件的过滤器
- 配置排除组件的过滤器
- 是否使用默认过滤器
- 是否配置懒加载
源码分析
由于此注解通常与 @Configuration 注解一起使用,其解析的主要逻辑都是在 refresh 阶段的 invokeBeanFactoryPostProcessors 方法中,最终会定位到 ConfigurationClassParser#doProcessConfigurationClass()
方法中,在方法中可以看到对 ComponentScan 注解的操作逻辑了

对注解属性的解析
所有对属性的解析都在 ComponentScanAnnotationParser#parse()
方法中进行,此方法中会创建一个 ClassPathBeanDefinitionScanner 实例scanner,此实例初始化过程中会对默认的Filter进行加载

然后会把配置的 includeFilter
和 excludeFilter
设置到 scanner 中,接着会对 basePackage
扫描包属性进行解析配置,如果配置了就添加,没有配置,默认就使用 @ComponentScan
注解标注类所在的包路径。解析完注解属性后,就开始了真正的扫描操作
扫描操作
扫描操作由 ClassPathBeanDefinitionScanner#doScan()
方法进行处理,此方法会调用 findCandidateComponents()
方法在给定的包下查找符合条件的组件,查找的任务由 scanCandidateComponents()
进行,该方法调用 isCandidateComponent()
方法,根据解析的includeFilter和excludeFilter 来选择满足条件的组件

这样扫描到所有满足条件的Bean后,会接着对这些Bean进行parse操作,直到注解再无其它依赖
注册Bean
扫描完所有Bean后,会调用 checkCandidate()
方法进行检查,检查当前要注册的Bean是否与已经注册过的Bean的定义是否兼容,如果冲突会报 ConflictingBeanDefinitionException
。检查没问题后,会调用 registerBeanDefinition()
方法对Bean进行注册,这个过程就涉及到Spring其它的生命周期了(这个后续专门学习总结),对于@ComponentScan 组件来说已经完成了它的使命
总结
最后以注解解析过程中的涉及的核心类做一下总结

常见问题
调整包结构后一些@Bean配置扫描不到了
- 调用启动类的包路径为最外层,这样可以扫描当前包及子包的配置
- 默认只扫描当前标注注解的包,可以通过配置
basePackage
属性指定扫描路径,配置后默认的扫描路径就不生效了
如何将未配置Spring相关组件注解的Bean纳入Spring管理?
可以通过配置 ComponentScan的includeFilter 来实现
|
|