Spring学习之@CompnentScan
注解说明 @ComponentScan 注解是Spring 提供的对组件进行扫描的注解指令,通常与 @Configuration 注解一起使用,支持在类上重复标注 注解能做什么? 此注解支持以下重要特性: 自定义扫描的包范围 配置包含扫描组件的过滤器 配置排除组件的过滤器 是否使用默认过滤器 是否配置懒加载 源码分析 由于此注解通常与 @Configuration 注解一起使用,其解析的主要逻辑都是在 refresh 阶段的 invokeBeanFactoryPostProcessors 方法中,最终会定位到 ConfigurationClassParser#doProcessConfigurationClass() 方法中,在方法中可以看到对 ComponentScan 注解的操作逻辑了 对注解属性的解析 所有对属性的解析都在 ComponentScanAnnotationParser#parse() 方法中进行,此方法中会创建一个 ClassPathBeanDefinitionScanner 实例scanner,此实例初始化过程中会对默认的Filter进行加载 处理默认Filter主要是 JSR-250 与 JSR-330 API 增加的注解 然后会把配置的 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 来实现 ...