Spring源码-注解版

Spring注解版执行流程 ClassPathBeanDefinitionScanner

上一篇文章讲到我们已经创建完bean定义信息读取器AnnotatedBeanDefinitionReader,代码接下来就到了创建ClassPathBeanDefinitionScanner的步骤。与之前步骤类似,useDefaultFilters默认传true,获取环境也是相同的步骤。
在这里插入图片描述
同样,我们看看ClassPathBeanDefinitionScanner的属性。
registry:我们创建的注解容器
beanDefinitionDefaults、autowireCandidatePatterns、includeAnnotationConfig
这三个属性暂时不知道有什么用。
beanNameGenerator、scopeMetadataResolver之前已经见过了。
在这里插入图片描述
进入构造方法,ClassPathBeanDefinitionScanner继承ClassPathScanningCandidateComponentProvider。registerDefaultFilters是给父类中的includeFilters属性赋值。
在这里插入图片描述
debug过程中,后面两个过滤器条件都不符合,添加失败。执行完成之后includeFilters属性中只有一个Component的过滤器。
在这里插入图片描述
设置环境和资源加载器都是给父类属性进行赋值。环境对象是注解容器中的环境对象。资源加载器是注解容器本身。至于里面的代码,暂时不看。
至此,注解容器对象的无参构造方法结束了。下一步进入register(componentClasses)方法。componentClasses是我们传入的主配置类。我们直接看第二行代码。使用我们之前创建的bean定义信息读取器去读取我们的主配置类。因为这里可以传入配置类数组,所以register方法里是循环遍历数组调用registerBean方法。
在这里插入图片描述
进入这个方法,除了beanClass是主配置类,其他参数都是null。方法第一步就是根据主配置类创建一个AnnotatedGenericBeanDefinition对象。这个对象也是bean定义信息对象的一个子类

	private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
			@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
			@Nullable BeanDefinitionCustomizer[] customizers) {
		// 创建一个AnnotatedGenericBeanDefinition对象
		AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
		if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
			return;
		}

在这个对象的构造方法中解析了主配置类的元数据信息
在这里插入图片描述
下面使用条件解析器解析解析主配置类元数据,判断是否跳过该类的加载。实际上查看主配置类上是否添加了Conditional注解。条件判断,如果满足条件就跳过加载。这里我的主类上没有条件注解。所以直接返回了。后续这里写个例子看看条件注解怎么生效的。
在这里插入图片描述
下面这三行代码。前两行的作用就是设置bean定义信息中的bean作用域。后一行就是是同名字生成器生成名字。

		//  解析主配置类上是否由Socpe注解,如果有,scopeMetadata 设置注解的值
		ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
        // 设置作用域
		abd.setScope(scopeMetadata.getScopeName());
		// 设置名字
		String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

determineBeanNameFromAnnotation里面的代码逻辑就是获取到配置类上的所有注解,循环遍历判断是否是Component注解并且value值不为空。最后返回beanName就是value中的值,如过此时beanName为空, buildDefaultBeanName(definition, registry)自动生成一个beanName并返回。里面的逻辑就是获取全限定名的最后一个,把第一个字母转成小写并返回。
在这里插入图片描述
这个方法里看当前配置类有没有其他的注解Lazy懒加载、Primary排序、DependsOn等。

AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);

这三行代码。第一行是对主类的bean定义信息进行包装,实际上没什么用,BeanDefinitionHolder 里面就三个属性。bean定义信息(beanDefinition)、bean的名字(beanName)和别名(aliases)。
第二行代码是判断是否需要设置代理。这里我还不懂。
第三行是将bean定义信息注册到beanDefinitionMap中去。这个时候,主配置类的信息就有了,后续拿主配置类信息进行操作。

BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
		definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
		BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);

我们看此时的beanDefinitionMap。前面5个是我们在创建AnnotatedBeanDefinitionReader对象的时候添加进去的,后面一个是我们的主启动类。到这里,我们前两个方法this()和register(componentClasses)就算结束了。后面就到了经典的12大方法refresh();
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值