spring源码:实例化bean的准备工作

本文探讨了在Spring实例化bean之前所进行的准备工作,主要包括使用AnnotationConfigApplicationContext初始化AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner,以及将配置类注册到BeanDefinitionMap中。通过对this()方法和register(annotatedClasses)的源码解析,揭示了配置类在扫描bean过程中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文内容

后面所有的笔记,都是基于Java配置形式来学习的,所以,默认情况下,都是以AnnotationConfigApplicationContext为例;本文主要记录,spring在真正开始初始化bean之前,需要完成的工作:大体主要包括三部分

  1. 初始化AnnotatedBeanDefinitionReader
  2. 初始化ClassPathBeanDefinitionScanner
  3. 将配置类注册到BeanDefinitionMap中

源码解析

前面文章有说过,通过 AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
的形式来启动spring,会进入到

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
	//在this()中调用父类的方法  创建了 DefaultListableBeanFactory(这就是平常说的springbean工厂)
	this();
	//把annotatedClasses(AppConfig.java)放到spring容器中
	register(annotatedClasses);
	refresh();
}

这个构造方法中,refresh()这个方法是spring初始化实例化bean的;this()和register(annotatedClasses);分别是初始化spring默认自带的后置处理器和将配置类注入到BeanDefinitionMap中

this()

public AnnotationConfigApplicationContext() {
	/**
	 * 创建一个读取注解的bean定义读取器
	 * bean定义其实就是beanDefinition
	 * 在这个方法里面 声明了六个比较重要的bean,并将这个几个bean存到了beanDefinitionMap里面
	 * CommonAnnotationBeanPostProcessor
	 * RequiredAnnotationBeanPostProcessor
	 * AutowiredAnnotationBeanPostProcessor
	 * ConfigurationClassPostProcessor
	 *
	 * 这里的reader主要完成了对配置类(@Configuration)的处理,将配置类添加到beanDefinitionMap中;
	 * 后面将普通bean扫描到beanDefinitionMap的时候,用的是另外new出来的scanner,并根据.class文件new出来一个ScannedGenericBeanDefinition对象
	 */
	this.reader = new AnnotatedBeanDefinitionReader(this);
	/**
	 * 实际上完成包扫描并不是这里的scanner完成的。而是spring自己new的一个ClassPathBeanDefinitionScanner完成的
	 * 这里的scanner是为了程序员能够在外部调用annotationConfigApplicationbContext对象,简单而言,spring遵循了开闭原则
	 *
	 * 这个方法里面的registerDefaultFilters这个方法也比较重要(这个方法有两个集合变量:includeFilters和excludeFilters),
	 *   在后面将class扫描出来并放到beanDefinitionMap的时候,有用到这个地方
	 * registerDefaultFilters 这个方法,向一个list(includeFilters)中添加了三个值
	 *   Component.class
	 *   javax.annotation.ManagedBean
	 *   javax.inject.Named
	 *
	 * 在扫描@ComponentScan下面的bean时,获取到的是包路径下所有的.class文件,那spring如何区分是要将哪些bean注入的呢?就和这里的includeFilters有关系。在后面包扫描会加注释
	 */
	this.scanner = new ClassPathBeanDefinitionScanner(this);
}

关于this()方法,里面只有两行代码,我对着两行代码完成的工作,在注释中,做了详细的介绍;就不再叙述了

register(annotatedClasses);

<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
			@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {

	/**
	 * 创建一个beanDefinition,beanDefinition保存了类的其他信息,比如:元注解信息、lazy属性等
	 */
	AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
	/**
	 * 判断是否需要跳过解析:应该是对@Conditional注解的判断
	 */
	if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
		return;
	}

	abd.setInstanceSupplier(instanceSupplier);
	ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
	//添加类的作用域
	abd.setScope(scopeMetadata.getScopeName());
	String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

	AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
	if (qualifiers != null) {
		for (Class<? extends Annotation> qualifier : qualifiers) {
			if (Primary.class == qualifier) {
				abd.setPrimary(true);
			}
			else if (Lazy.class == qualifier) {
				abd.setLazyInit(true);
			}
			else {
				abd.addQualifier(new AutowireCandidateQualifier(qualifier));
			}
		}
	}
	for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
		customizer.customize(abd);
	}

	//beanDefinitionHolder也是一种数据结构 先暂时认为definitionHolder比beanDefinition存储的信息更为丰富
	BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
	definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
	/**
	 * 这是是把创建的definitionHolder注册到registry
	 * registry就是AnnotationConfigApplicationContext初始化创建的DefaultListableBeanFactory
	 *
	 * 内部调用的是DefautListableBeanFactory.registerBeanDefinition()方法
	 */
	BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}

这里之所以将配置类,加入到BeanDefinitionMap中,我觉得是因为在后面扫描bean的时候,需要用到配置类中的@ComponentScan注解,所以,在之前,先将配置类添加到beanDefinitionMap中

这是这两个方法的解析和学习,后面的文章中,我们来看refresh完成的工作

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值