spring源码-bean加载整体流程

本文深入探讨Spring框架中bean的加载过程,从入口`refresh()`方法开始,涉及`this()`、`register(annotatedClasses)`等关键步骤。文章详细阐述了配置类的解析、`BeanDefinition`注册、过滤器的使用以及`ComponentScan`注解的作用。通过分析`refresh()`方法内的`invokeBeanFactoryPostProcessors(beanFactory)`和`finishBeanFactoryInitialization(beanFactory)`,揭示了bean初始化、实例化及AOP动态代理的秘密。

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

内容概述

本文主要记录spring源码中初始化、实例化bean的整体流程,后面会单独拆开分析spring在初始化中的详细步骤;我在学习的时候,是以Java配置的方式,来学习spring的。所以,就以AnnotationConfigApplicationContext为例了

入口

在spring启动的时候,会通过AbstractApplicationContext的子类来初始化,如果我们指定了对应的配置类,会通过下面的构造函数开始spring的初始化

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
    this();
	register(annotatedClasses);
	refresh();
}
这个方法中,有三个方法,来依次分析三行代码完成的操作

this()

先说这代码完成的操作:
1、初始化了一个AnnotatedBeanDefinitionReader()对象,在初始化该对象的时候,将spring在后面对业务类进行初始化时,需要用到的一些后置处理器,存入了beanDefinitionMap中,我们姑且称这些为spring自带的beanPostProcessor和beanFactoryPostProcessor;
org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object)
这个方法中,将spring自带的beanPostProcessor和beanFactoryPostProcessor放到了beanDefinitionMap中;可以debug一下来看下

  • ConfigurationClassPostProcessor
  • AutowiredAnnotationBeanPostProcessor
  • CommonAnnotationBeanPostProcessor
  • EventListenerMethodProcessor
  • DefaultEventListenerFactory
  • PersistenceAnnotationBeanPostProcessor

在这几个bean中,有一个bean需要特别注意一下,ConfigurationClassPostProcessor;这个类是BeanDefinitionRegistryPostProcessor的实现类,BeanDefinitionRegistryPostProcessor又是BeanFactoryPostProcessor的子接口,这个类在扫描bean的时候 有用到;这几个类,后面学习spring扫描bean的时候会详细介绍
在这里插入图片描述

2、初始化了一个ClassPathBeanDefinitionScanner对象,在初始化该对象的时候,对两个list集合进行了赋值
private final List includeFilters = new LinkedList<>();
private final List excludeFilters = new LinkedList<>();
这两个list集合,在spring扫描bean的时候,会用到,因为spring在扫描bean的时候,会把某个路径下所有的class都扫描出来,扫描出来的,不一定是我们需要注入的业务类,只有加了@Component注解的bean,才会被spring来管理,就和这两个list集合有关系;

org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#registerDefaultFilters

在这个类中,将@Component注解添加到了includeFilters集合中

register(annotatedClasses);

在这个方法中,是把构造方法中,传过来的配置类,添加到了BeanDefinitionMap中,这里之所以,将配置类添加到beanDefinitionMap中,是因为在后面,对bean进行扫描的时候,需要用到配置类中的@ComponentScan注解中对应package
这里说的配置类就是加了@Configuration注解的类;所以需要在这里,提前把配置类先行解析,然后放到beanDefinitionMap中;需要注意的是,这里只是把配置类转换成了beanDefinition对象,并没有对配置类进行初始化

refresh()

refresh方法,是spring初始化的核心方法,在refresh中,完成了对bean的初始化、实例化、注入等;


@Override
public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
		// Prepare this context for refreshing.
		//准备工作包括设置启动时间、是否激活标志位、初始化属性源配置
		prepareRefresh();

		// Tell the subclass to refresh the internal bean factory.
		/**
		 * 返回一个factory
		 * xml格式的配置文件,是在这个方法中扫描到beanDefinitionMap中的
		 * 在org.springframework.web.context.support.XmlWebApplicationContext#loadBeanDefinitions(org.springframework.beans.factory.support.DefaultListableBeanFactory)中会创建一个XmlBeanDefinitionReader来解析xml文件
		 * 会把bean.xml解析成一个InputStream,然后再解析成document格式
		 * 按照document格式解析,从root节点进行解析,判断root节点是bean?还是beans?还是import等,如果是bean
		 * 就把解析到的信息包装成beanDefinitionHolder,然后调用DefaultListablebeanFactory的注册方法将bean放到beanDefinitionMap中
		 */
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

		// Prepare the bean factory for use in this context.
		//准备工厂
		prepareBeanFactory(beanFactory);

		try {
			// Allows post-processing of the bean factory in context subclasses.
			//空方法,留给子类去自定义
			postProcessBeanFactory(beanFactory);

			// Invoke factory processors registered as beans in the context.
			/**
			 * TODO
			 * 完成对bean的扫描,将class变成beanDefinition,并将beanDefinition存到map中
			 *
			 * 该方法在spring的环境中执行已经被注册的factory processors;
			 * 执行自定义的processBeanFactory
			 *
			 * 在这个方法中,注入bean,分为了三种
			 * 一、普通bean:@Component注解的bean
			 * spring 自己的类,不借助spring扫描,会直接放到beanDefinitionMap
			 *
			 * 1.获取到所有的beanFactoryPostProcessor
			 * 2.执行 bean后置处理器的postProcessBeanFactory(configurationClassPostProcessor),该方法会把beanFactory作为入参传到方法里面
			 * 3.从beanFactory中获取到所有的beanName   打断点看一下 org.springframework.context.annotation .ConfigurationClassPostProcessor#processConfigBeanDefinitions
			 *
			 * 4.然后将所有的bean包装成beanDefinitionHolder,在后面又根据beanName和bean的metadata包装成了ConfigurationClass
			 * 5.把所有包含@ComponentScan的类取出来,遍历每一个componentScan,调用 ClassPathBeanDefinitionScanner.doScan(basePackages)方法
			 * 6.在doScan方法中,会遍历basePackages,因为一个ComponentScan中可以配置多个要扫描的包
			 * 7.获取每个包下面的 *.class文件,registerBeanDefinition(definitionHolder, this.registry); 这个方法底层就是调用org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinition方法  把当前bean put到beanDefinitionMap中
			 *
			 * 二、是通过@Import注解注入的bean
			 *     ImportBeanDefinitionRegistrar
			 *     ImportSelector
			 *
			 * 三、@Bean注解
			 *
			 *
			 *
			 * spring在把bean注入到beanDefinitionMaps的同时,会将当前beanName添加到一个list中 beanDefinitionNames,这个list和beanDefinitionMap是同时进行添加的,这个list在后面实例化bean的时候有用到,spring是遍历这个list,拿到每个beanName之后,从beanDefinitionMap中取到对应的beanDefinition
			 */
			invokeBeanFactoryPostProcessors(beanFactory);

			// Register bean processors that intercept bean creation.
			/**
			 *  注册beanPostProcessor;方法里面
			 *  会先把beanPostProcessor进行分类,然后按照beanPostProcessor的name从spring容器中获取bean对象,如果spring容器中没有,就创建;所以如果一个beanDefinition是后置处理器,会这这里进行实例化,然后存放到单实例池中
			 *  然后再调用的是 beanFactory.addBeanPostProcessor(postProcessor);
			 * 把所有的beanPostProcessor放到了beanPostProcessors中,在后面初始化bean的时候,如果需要调用后置处理器,就会遍历这个list,
			 */

			registerBeanPostProcessors(beanFactory);

			// Initialize message source for this context.
			//初始化MessageSource组件(该组件在spring中用来做国际化、消息绑定、消息解析)
			initMessageSource();

			// Initialize event multicaster for this context.
			/**
			 * 注册一个多事件派发器
			 * 先从beanFactory获取,如果没有,就创建一个,并将创建的派发器放到beanFactory中
			 */
			initApplicationEventMulticaster();

			// Initialize other special beans in specific context subclasses.
			/**
			 * 这是一个空方法,在springboot中,如果集成了Tomcat,会在这里new Tomcat(),new DispatcherServlert();
			 */
			onRefresh();

			// Check for listener beans and register them.
			/**
			 * 注册所有的事件监听器
			 * 将容器中的时间监听器添加到 applicationEventMulticaster 中
			 *
			 */
			registerListeners();

			// Instantiate all remaining (non-lazy-init) singletons.
			/**
			 * TODO
			 * 完成对bean的实例化
			 *
			 * 主要的功能都在这里面
			 */
			finishBeanFactoryInitialization(beanFactory);

			// Last step: publish corresponding event.
			/**
			 * 当容器刷新完成之后,发送容器刷新完成事件
			 * publishEvent(new ContextRefreshedEvent(this));
			 */
			finishRefresh();
		}
		catch (BeansException ex) {
			if (logger.isWarnEnabled()) {
				logger.warn("Exception encountered during context initialization - " +
						"cancelling refresh attempt: " + ex);
			}

			// Destroy already created singletons to avoid dangling resources.
			//调用bean的销毁方法
			destroyBeans();

			// Reset 'active' flag.
			cancelRefresh(ex);

			// Propagate exception to caller.
			throw ex;
		}
		finally {
			// Reset common introspection caches in Spring's core, since we
			// might not ever need metadata for singleton beans anymore...
			resetCommonCaches();
		}
	}
}

在refresh方法中,比较重要的是这两个方法

  1. invokeBeanFactoryPostProcessors(beanFactory);
    这个方法完成了业务类的扫描,也就是对@ComponentScan注解标识的包进行扫描,将我们要注入到spring中的业务类,添加到BeanDefinitionMap中
  2. finishBeanFactoryInitialization(beanFactory);
    这个方法主要是对beanDefinitionMap中的业务类进行初始化、实例化、AOP动态代理等

这是AnnotationCongigApplicationContext构造方法的三行代码完成的操作

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值