AnnotationConfigApplicationContext 通过调用类路径Bean 定义扫描器ClassPathBeanDefinitionScanner 扫描给定包及其子包下的所有类,主要源码如下:

public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider {private final BeanDefinitionRegistry registry;private BeanDefinitionDefaults beanDefinitionDefaults = new BeanDefinitionDefaults();@Nullableprivate String[] autowireCandidatePatterns;private BeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator();private ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver();private boolean includeAnnotationConfig = true;//创建一个类路径Bean定义扫描器public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {this(registry, true);}//为容器创建一个类路径Bean定义扫描器,并指定是否使用默认的扫描过滤规则。//即Spring默认扫描配置:@Component、@Repository、@Service、@Controller//注解的Bean,同时也支持JavaEE6的@ManagedBean和JSR-330的@Named注解public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {this(registry, useDefaultFilters, getOrCreateEnvironment(registry));}public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,Environment environment) {this(registry, useDefaultFilters, environment,(registry instanceof ResourceLoader ? (ResourceLoader) registry : null));}public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,Environment environment, @Nullable ResourceLoader resourceLoader) {Assert.notNull(registry, "BeanDefinitionRegistry must not be null");//为容器设置加载Bean定义的注册器this.registry = registry;if (useDefaultFilters) {registerDefaultFilters();}setEnvironment(environment);//为容器设置资源加载器setResourceLoader(resourceLoader);}@Overridepublic final BeanDefinitionRegistry getRegistry() {return this.registry;}public void setBeanDefinitionDefaults(@Nullable BeanDefinitionDefaults beanDefinitionDefaults) {this.beanDefinitionDefaults =(beanDefinitionDefaults != null ? beanDefinitionDefaults : new BeanDefinitionDefaults());}public BeanDefinitionDefaults getBeanDefinitionDefaults() {return this.beanDefinitionDefaults;}public void setAutowireCandidatePatterns(@Nullable String... autowireCandidatePatterns) {this.autowireCandidatePatterns = autowireCandidatePatterns;}public void setBeanNameGenerator(@Nullable BeanNameGenerator beanNameGenerator) {this.beanNameGenerator = (beanNameGenerator != null ? beanNameGenerator : new AnnotationBeanNameGenerator());}public void setScopeMetadataResolver(@Nullable ScopeMetadataResolver scopeMetadataResolver) {this.scopeMetadataResolver =(scopeMetadataResolver != null ? scopeMetadataResolver : new AnnotationScopeMetadataResolver());}public void setScopedProxyMode(ScopedProxyMode scopedProxyMode) {this.scopeMetadataResolver = new AnnotationScopeMetadataResolver(scopedProxyMode);}public void setIncludeAnnotationConfig(boolean includeAnnotationConfig) {this.includeAnnotationConfig = includeAnnotationConfig;}//调用类路径Bean定义扫描器入口方法public int scan(String... basePackages) {//获取容器中已经注册的Bean个数int beanCountAtScanStart = this.registry.getBeanDefinitionCount();//启动扫描器扫描给定包doScan(basePackages);// Register annotation config processors, if necessary.//注册注解配置(Annotation config)处理器if (this.includeAnnotationConfig) {AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);}//返回注册的Bean个数return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);}//类路径Bean定义扫描器扫描给定包及其子包protected Set<BeanDefinitionHolder> doScan(String... basePackages) {Assert.notEmpty(basePackages, "At least one base package must be specified");//创建一个集合,存放扫描到Bean定义的封装类Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();//遍历扫描所有给定的包for (String basePackage : basePackages) {//调用父类ClassPathScanningCandidateComponentProvider的方法//扫描给定类路径,获取符合条件的Bean定义Set<BeanDefinition> candidates = findCandidateComponents(basePackage);//遍历扫描到的Beanfor (BeanDefinition candidate : candidates) {//获取Bean定义类中@Scope注解的值,即获取Bean的作用域ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);//为Bean设置注解配置的作用域candidate.setScope(scopeMetadata.getScopeName());//为Bean生成名称String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);//如果扫描到的Bean不是Spring的注解Bean,则为Bean设置默认值,//设置Bean的自动依赖注入装配属性等if (candidate instanceof AbstractBeanDefinition) {postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);}//如果扫描到的Bean是Spring的注解Bean,则处理其通用的Spring注解if (candidate instanceof AnnotatedBeanDefinition) {//处理注解Bean中通用的注解,在分析注解Bean定义类读取器时已经分析过AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);}//根据Bean名称检查指定的Bean是否需要在容器中注册,或者在容器中冲突if (checkCandidate(beanName, candidate)) {BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);//根据注解中配置的作用域,为Bean应用相应的代理模式definitionHolder =AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);beanDefinitions.add(definitionHolder);//向容器注册扫描到的BeanregisterBeanDefinition(definitionHolder, this.registry);}}}return beanDefinitions;} }

类路径Bean 定义扫描器ClassPathBeanDefinitionScanner 主要通过findCandidateComponents()方法调用其父类ClassPathScanningCandidateComponentProvider 类来扫描获取给定包及其子包下的类。

ClassPathBeanDefinitionScanner 扫描给定的包及其子包相关推荐

  1. SSIS 父子包,子包调用父包变量

    学习内容来自于 天善学院 的视频 目录 介绍背景 正题:子包获取父包变量 介绍背景 背景: 父包与子包都执行 SQL TASK(向数据库 LOG表 插入一条记录) LOG表 内会有字段对应 当前包ID ...

  2. ClassPathScanningCandidateComponentProvider 扫描给定包及其子包的类

    ClassPathScanningCandidateComponentProvider 类的findCandidateComponents()方法具体实现扫描给定类路径包的功能,主要源码如下: //保 ...

  3. vite打包类库的时候,总包和子包区分打包,怎么打包出来的都是总包的内容

    需求 作者想打包一个组件库,输出可按需加载的总包的同时,并希望将每个组件进行打包输出,这样的话 1.可以批量或按需引用总包 2.也可以引用个别组件,无需引用总包,使得每个组件都可以单独运行,独立使用. ...

  4. IntelliJ IDEA怎么创建package包下面的子包

    IntelliJ IDEA怎么创建package包下面的子包 当你打开如此界面时,确实无法在com.company下面新建子包,因为这个包里面什么也没有,无法支撑你新建子包,那么这个时候可以先在当前包 ...

  5. python哪里下载import包-【Python包】模块和包导入详解(import)

    1.模块(module) 1.1 模块定义 通常模块为一个.py文件,其他可作为module的文件类型还有".pyo".".pyc".".pyd&qu ...

  6. Java项目 常用包的命名及理解【dao包、domain包、service包、utils包、web包、impl包】

    JavaWeb 黑马旅游网 项目结构:       目录 1.dao包 2.domain包 3.service包 4.utils包 5.web包 6.impl包 1.dao包 Dao:数据库相关操作 ...

  7. java 包 划分_Java包的命名与划分

    同事昨天接收到这样一份任务:梳理现在Android项目中"顶层包"的依赖关系,从而进行层次结构的梳理. 在一起的探索的过程中,发觉收获还是蛮大的,灵感突发,马上梳理于此. (一)使 ...

  8. eclipse中在包内建包

    Package Explorer下有一个点击View Menu 点击Package Presentation 选中Hierarchical,将视图从平铺模式变成按等级划分 右键包,新建包,子包名为父包 ...

  9. Java包名与包路径

    很多初学者以为只要把生成的class文件放在某个目录下,这个目录名就成了这个类的包名.这是一个错误的看法,不是有了目录 结构,就等于有了包名.为Java类添加包必须在Java源文件中通过 packag ...

最新文章

  1. 条件随机场(CRF) - 2 - 定义和形式
  2. OpenCV(十九)直方图(直方图计算、掩膜、均衡化、自适应均衡化)
  3. Tomcat User 配置
  4. Quartz 在 Spring 中如何动态配置时间
  5. 二叉树的递归遍历与复制
  6. 搭建FastDFS分布式文件存储系统教程
  7. Android AutoCompleteTextView自动提示文本框
  8. python教程七牛云_python-django框架中使用七牛云
  9. mongodb java 嵌套查询_MongoDB java 查询嵌套JSON数据?
  10. 购房者一次性付清和还贷三十年,差别有多大?
  11. stream场景用法总结
  12. Reset Password Windows Server 2008 r2
  13. Leetcode 224.基本计算器
  14. Unity3d FPS射击游戏案例 - 消灭病毒
  15. bzoj-4318 OSU! 【数学期望】
  16. xilinx芯片的 IOB 以及 IOB = false
  17. 10个Excel实用操作技巧分享,使用率超高,让你一学就会
  18. error LNK2023: bad DLL or entry point 'msobj80.dll' 解决方法
  19. 字符设备驱动、平台设备驱动、设备驱动模型、sysfs的比较和关联
  20. 理解和使用alsa配置-默认静音,必须先用amixer解除主音量和pcm音量的静音

热门文章

  1. 设计模式- 策略模式
  2. Groovy预览--文本处理
  3. 2019.6.18 校内测试 分析+题解
  4. df=df.reset_index(drop=True)
  5. 知道这些面试技巧,让你的测试求职少走弯路
  6. 上古神器之Vim编辑器
  7. Java 集合框架部分面试题
  8. fastjson使用中遇到的
  9. DataSet DataTable操作
  10. Cordova学习--iOS自定义插件