ClassPathBeanDefinitionScanner 扫描给定的包及其子包
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 扫描给定的包及其子包相关推荐
- SSIS 父子包,子包调用父包变量
学习内容来自于 天善学院 的视频 目录 介绍背景 正题:子包获取父包变量 介绍背景 背景: 父包与子包都执行 SQL TASK(向数据库 LOG表 插入一条记录) LOG表 内会有字段对应 当前包ID ...
- ClassPathScanningCandidateComponentProvider 扫描给定包及其子包的类
ClassPathScanningCandidateComponentProvider 类的findCandidateComponents()方法具体实现扫描给定类路径包的功能,主要源码如下: //保 ...
- vite打包类库的时候,总包和子包区分打包,怎么打包出来的都是总包的内容
需求 作者想打包一个组件库,输出可按需加载的总包的同时,并希望将每个组件进行打包输出,这样的话 1.可以批量或按需引用总包 2.也可以引用个别组件,无需引用总包,使得每个组件都可以单独运行,独立使用. ...
- IntelliJ IDEA怎么创建package包下面的子包
IntelliJ IDEA怎么创建package包下面的子包 当你打开如此界面时,确实无法在com.company下面新建子包,因为这个包里面什么也没有,无法支撑你新建子包,那么这个时候可以先在当前包 ...
- python哪里下载import包-【Python包】模块和包导入详解(import)
1.模块(module) 1.1 模块定义 通常模块为一个.py文件,其他可作为module的文件类型还有".pyo".".pyc".".pyd&qu ...
- Java项目 常用包的命名及理解【dao包、domain包、service包、utils包、web包、impl包】
JavaWeb 黑马旅游网 项目结构: 目录 1.dao包 2.domain包 3.service包 4.utils包 5.web包 6.impl包 1.dao包 Dao:数据库相关操作 ...
- java 包 划分_Java包的命名与划分
同事昨天接收到这样一份任务:梳理现在Android项目中"顶层包"的依赖关系,从而进行层次结构的梳理. 在一起的探索的过程中,发觉收获还是蛮大的,灵感突发,马上梳理于此. (一)使 ...
- eclipse中在包内建包
Package Explorer下有一个点击View Menu 点击Package Presentation 选中Hierarchical,将视图从平铺模式变成按等级划分 右键包,新建包,子包名为父包 ...
- Java包名与包路径
很多初学者以为只要把生成的class文件放在某个目录下,这个目录名就成了这个类的包名.这是一个错误的看法,不是有了目录 结构,就等于有了包名.为Java类添加包必须在Java源文件中通过 packag ...
最新文章
- 条件随机场(CRF) - 2 - 定义和形式
- OpenCV(十九)直方图(直方图计算、掩膜、均衡化、自适应均衡化)
- Tomcat User 配置
- Quartz 在 Spring 中如何动态配置时间
- 二叉树的递归遍历与复制
- 搭建FastDFS分布式文件存储系统教程
- Android AutoCompleteTextView自动提示文本框
- python教程七牛云_python-django框架中使用七牛云
- mongodb java 嵌套查询_MongoDB java 查询嵌套JSON数据?
- 购房者一次性付清和还贷三十年,差别有多大?
- stream场景用法总结
- Reset Password Windows Server 2008 r2
- Leetcode 224.基本计算器
- Unity3d FPS射击游戏案例 - 消灭病毒
- bzoj-4318 OSU! 【数学期望】
- xilinx芯片的 IOB 以及 IOB = false
- 10个Excel实用操作技巧分享,使用率超高,让你一学就会
- error LNK2023: bad DLL or entry point 'msobj80.dll' 解决方法
- 字符设备驱动、平台设备驱动、设备驱动模型、sysfs的比较和关联
- 理解和使用alsa配置-默认静音,必须先用amixer解除主音量和pcm音量的静音