Spring容器创建过程,源码分析-springbean的生命周期源码分析

Spring容器创建过程

注意:Spring5.3.9,一个启动类,未自定义任何钩子执行的整个流程。如有任何疑问欢迎讨论!

使用全注解开发,Spring在AnnotationConfigApplicationContext的构造函数中调用了三个方法

  1. 空参构造方法
  2. register启动类
  3. refresh容器

空参构造方法——准备工作

空参方法做准备工作

  • DefaultListableBeanFactory:默认Bean工厂
    关键在Bean工厂,其中包含了bean定义的map集合、bean后置处理器集合等,部分代码如下(包含该类和其父类):

/** Cache of singleton objects: bean name to bean instance. */
/* 一级缓存 */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

/** Cache of singleton factories: bean name to ObjectFactory. */
/* 二级缓存 */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

/** Cache of early singleton objects: bean name to bean instance. */
/* 三级缓存 */
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);

/** Map of bean definition objects, keyed by bean name. */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

/** Disposable bean instances: bean name to disposable instance. */
private final Map<String, Object> disposableBeans = new LinkedHashMap<>();

/** BeanPostProcessors to apply. */
private final List<BeanPostProcessor> beanPostProcessors = new BeanPostProcessorCacheAwareList();
  • ProtocolResolverResourcePatternResolverDefaultResourceLoader:负责处理资源
  • Environment:容器的环境
  • AnnotatedBeanDefinitionReader:解析Bean注解
    • ConditionEvaluator:解析@Conditional类注解
    • BeanNameGenerator:生成bean名
    • scopeMetadataResolver:bean的scope相关信息
  • ClassPathBeanDefinitionScanner
  • List<BeanFactoryProcessor>:工厂处理器集合
  • Set<ApplicationListener<?>>:监听器集合

包括但不限于上述,大多见名知义,做的都是一些准备工作。
到这里,beanDefinitionMap中Spring默认添加了几个intenalxxxx用于完成容器的创建。

register——启动类注册

register方法就几行代码,主要的逻辑在AnnotatedBeanDefinitionReader中的doRegisterBean中,该方法对每个启动类做了以下几件事:

  1. 检查@Conditional注解,是否需要扫描该类
  2. 获取该类的scope元数据,处理@Primary、@Lazy、ProxyMode等
  3. 加入到beanDefinitionMap

refresh方法

prepareRefresh

  1. 更新容器状态
  2. 个性化属性设置,子类重写initPropertySource,默认空实现
  3. 检测当前容器环境是否缺少属性值
  4. 准备好事件监听,事件监听器集合与事件集合

obtainRefreshBeanfactory

  1. 设置beanFactory状态refreshed为true
  2. 设置序列化id,支持beanFactory的反序列化,使用到了弱引用

prepareBeanFactory

  1. 设置Bean的类加载器,使用上下文的类加载器。更多关于Java类加载的内容
  2. 设置spel表达式解析器
  3. 设置PropertyEditor(Bean创建时用于操作属性)注册器
  4. 设置忽略的自动装配接口(XXXXAware)与可直接自动装配的(AppContext、BeanFactory等)
  5. 添加ApplicationListenerDetector,是一个BeanPostProcessor,处理ApplicationListenerBean,要求事件监听器为单例。
  6. 注册默认环境Bean(systemProperties、systemEnvironment等)

postProcessBeanFactory

该方法默认空实现,此时beanDefininationMap仍然只有Spring默认的个类(intenalxxx)及我们自己的启动类,已经注入容器的是systemProperties、systemEnvironment等类。重写这个函数可以在工厂初始化后进行自定义修改

invokeBeanFactoryPostProcessor

如果对Spring的各种PostProcessor不够熟悉的话,建议阅Spring PostProcessor

这个函数很长,就是调用所有BeanFactoryProcessor的过程
在这些postProcessor中,其中有一个关键的ConfigurationClassPostProcessor,在org.springframework.context.annotation包下,顾名思义,处理@Configuration注解。
整理一下,目前,beanDefinitionMap中只有Spring默认注入的几个类用于构建容器的类以及我们的启动配置类
下面方法用于扫描beanDefinitionMap中的每个beanDefinition

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
	/* 待扫描的配置类 */
	List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
	/* 获取所有beanDefinition */
	String[] candidateNames = registry.getBeanDefinitionNames();
	for (String beanName : candidateNames) {
		BeanDefinition beanDef = registry.getBeanDefinition(beanName);
		/* 已被当作配置类处理 */
		if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
			/* 无关代码 */
		}
		/* 判断是否是配置类 */
		else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
			/* 添加为待处理配置类 */
			configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
		}
	}	
	// 未找到配置类
	if (configCandidates.isEmpty()) {
		return;
	}

	// 排序,对应@Order等注解
	configCandidates.sort((bd1, bd2) -> {
		int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
		int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
		return Integer.compare(i1, i2);
	});
	...
}

checkConfigurationClassCandidate函数,如下

/* 获取注解元数据 */
AnnotationMetadata metadata;
if ({...}
else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {
	// Check already loaded Class if present...
	// since we possibly can't even load the class file for this Class.
	Class<?> beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass();
	if (BeanFactoryPostProcessor.class.isAssignableFrom(beanClass) ||
			BeanPostProcessor.class.isAssignableFrom(beanClass) ||
			AopInfrastructureBean.class.isAssignableFrom(beanClass) ||
			EventListenerFactory.class.isAssignableFrom(beanClass)) {
		return false;
	}
	metadata = AnnotationMetadata.introspect(beanClass);
	}
	else {metadata=...}
/* 注解元数据获取完毕 */

/* 是否是配置类 */
/* @Configuration注解 */
Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
/* lite模式和full模式 */
if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
	/* 记录已被扫描 */
	beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
}
else if (config != null || isConfigurationCandidate(metadata)) {
	beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
}
else {
	return false;
}
/* 判断完毕 */
// It's a full or lite configuration candidate... Let's determine the order value, if any.
Integer order = getOrder(metadata);
if (order != null) {
	beanDef.setAttribute(ORDER_ATTRIBUTE, order);
}
return true;

到目前我们扫描出了对应的配置类,但还未解析该类,解析过程是由ConfigurationClassParser完成的,主要在其doProcessConfigurationClass方法,代码较长,只截取了部分

protected final SourceClass doProcessConfigurationClass(
			ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
			throws IOException {
	/* 优先处理内部类 */
	if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
		// Recursively process any member (nested) classes first
		processMemberClasses(configClass, sourceClass, filter);
	}
	
	// @PropertySource注解
	for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
			sourceClass.getMetadata(), PropertySources.class,
			org.springframework.context.annotation.PropertySource.class)) {
		if (this.environment instanceof ConfigurableEnvironment) {
			processPropertySource(propertySource);
		}
		else {...}
	}

	// 处理 @ComponentScan
	...
	// Process any @Import annotations
	// Process any @ImportResource annotations
	// Process individual @Bean methods
	// Process default methods on interfaces
	// Process superclass, if any
 	// No superclass -> processing is complete
	...
	}

具体的实现细节都在ConfigurationClassParser中,可自行阅读。
另外,在org.springframework.context.annotation包下,可以看到很多用于解析注解数据的类,如AnnocationBeanDefinitionReader、ComponentScanAnnotationParser等,CondtionalEvaluator等,可以说这个包主要是负责容器的建立。
此时,所有需要加入到容器中的类全都被扫描加入到了BeanDefinitionMap中,beanFactory的sigletonObjects有默认添加的用于初始化容器的类以及systemProperties等

registerBeanPostProcessors

从beanFactory中获取所有实现BeanPostProcessor接口的类,注册等待后续处理bean,我们自己写的实现BeanPostProcessor接口的类(已在beanDefinitionMap中)在此时被注册。该方法主要逻辑如下:

  1. 通过beanFactory.getBeanNamesForTyp获取所有BeanPostProcessor,此时它们还未被实例化,只是在beanDefinitionMap中。
  2. 通过getBean方法获取bean实例,在getBean方法中,因为还未实例化,所以会会进行一系列实例化、初始化流程,这些BeanPostProcessor相较于普通bean被提前初始化完毕。
    所以,按照容器的初始化流程来说,BeanFactoryPostProcessor、BeanPostProcessor是无法与我们的普通bean实例交互的,具体来说,在其中Autowire普通的bean会警告或报错
  3. 按照是否实现PriorityOrdered、Ordered接口为所有的BeanPostProcessr排序.
  4. 添加到beanFactory的beanPostProcessor集合中。

初始化消息源——initMessageSource

Spring MessageSource

事件派发器:initApplicationEventMulticaster

初始化事件派发器,关于Spring的事件监听,可以看这Spring 中ApplicationListener

onRefresh

自己写的类目前都在BeanDefinitionMap中,还未进行实例化与属性注入
onfresh函数允许在这个时候做一些事,比如添加bean到beanDefininationMap。

为事件派发器注册监听器:registerListeners

  1. 注册监听器
  2. 收集派发器之前发生的事件
    我们自己写的ApplicationListener在此时被注册,同样是从beanFactory中取得

finishBeanFactoryInitialization

完成此上下文的 bean 工厂的初始化,初始化所有剩余的单例bean
网上流传的面试问题Spring Bean的生命周期大概说的这个地方,因为此时容器中只有Spring为整个ApplicationContext能正常运行而注入的Bean,我们自己写的仍然只在beanDefinitionMap中,在DefaulListableBeanFactory的preInstantiateSingletons方法中:

/* 这个里面包含了所有的beanDefinition */
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
for (String beanName : beanNames) {
	RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
	if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
	if (isFactoryBean(beanName)) {
		/* 这个PREFIXX就是&,在上一篇文章中有提到 */
		Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
		...
	}else{
		/* 尝试从容器中获取 */
		getBean(beanName);
	}

getBean方法之后一直在beanFactory中进行函数调用,我们重点关注getSingleton方法

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // Quick check for existing instance without full singleton lock
    Object singletonObject = this.singletonObjects.get(beanName);
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
    singletonObject = this.earlySingletonObjects.get(beanName);
    if (singletonObject == null && allowEarlyReference) {
        synchronized (this.singletonObjects) {
            // Consistent creation of early reference within full singleton lock
            singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
                singletonObject = this.earlySingletonObjects.get(beanName);
                if (singletonObject == null) {
                   ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
	           if (singletonFactory != null) {
		       singletonObject = singletonFactory.getObject();
  		       this.earlySingletonObjects.put(beanName, singletonObject);
		       this.singletonFactories.remove(beanName);
	           }
                }
             }
          }
       }
    }
    return singletonObject;
}
  1. 尝试从singletonObjetcs中获取bean,若为null且当前bean正在创建中,转到2;否则返回null
  2. 尝试从earlySingletonObjects中获取,

收尾——finishRefresh

  1. 清资源缓存
  2. 初始化lifecycleProcessor
  3. refresh,bean生命周期开始
  4. 发布初始化完成事件
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值