Spring专题源码解析(二)Spring容器刷新时的初始化容器时的单实例bean的流程。

前文:在Spring专题源码解析(一)中我们对Spring容器初始化时的整体流程进行了解析,和容器初始化时beanFactory和各种PostProsessor后置处理器进行了解析说明,本篇我们主要讲解容器初始化时的一个初始化剩下单实例bean的整体流程。主要是下面这个方法。finishBeanFactoryInitialization(beanFactory);本篇幅我们主要来讲解这个方法。

一、讲本篇中要解析的几个接口和类和属性。

1、RootBeanDefinition 该类与AbstractBeanDefinition是互补关系,RootBeanDefinition在AbstractBeanDefinition的基础上定义了更多属性,初始化Bean需要的信息基本完善。
2、AbstractBeanFactory 该抽象类是BeanFactory(容器顶级接口)的抽象实现。
3、AbstractAutowireCapableBeanFactory 这是抽象类,该类继承了AbstractBeanFactory类,以及实现AutowireCapableBeanFactory的接口。
4、DefaultListableBeanFactory 是一个真正可以 new 出来的具体的容器,当然也可以暂且称之为 bean 工厂。
5、SingletonBeanRegistry 一个非常重要的接口,用于注册,获得,管理singleton对象。目前唯一的实现是DefaultSingletonBeanRegistry。
6、DefaultListableBeanFactory 中的属性:
List beanDefinitionNames 存放bean名称的List集合。
Map<String, BeanDefinition> beanDefinitionMap 存储注册信息的BeanDefinition。
7、DefaultSingletonBeanRegistry类中的属性(介绍3个Map):
Map<String, Object> singletonObjects,一级缓存Map(存放单实例bean(经历完成生命周期的bean))。
Map<String, ObjectFactory<?>> singletonFactories 二级缓存Map(存放单实例bean的名称和创建bean的工厂)。
Map<String, Object> earlySingletonObjects 三级缓存Map(存放单实例bean的名称和bean早期的实例(没有经历完成生命周期的早期的bean对象))。

二、源码解析流程。

Spring版本: 5.0.2.RELEASE版本。
流程步骤:
在这里插入图片描述

1.进入到刷新refresh()方法
2.finishBeanFactoryInitialization()初始化所有单例对象
3.preInstantiateSingletons()初始化所有的单例对象:注意是非懒加载
4、getBean(beanName)->doGetBean()->createBean()->doCreateBean()->createBeanInstance()初始化对象(默认情况下使用Java反射机制初始化对象,也可以通过CGLIB)
5.populateBean()给对象的set属性赋值
6.initializeBean()执行初始化方法(也可以自己定义初始化的方法)
6.1.invokeAwareMethods()判断bean的类型是否是Aware相关依赖,如果存在的情况回调方法
6.2.applyBeanPostProcessorsBeforeInitialization()在初始化方法之前执行处理(增强)
6.3.invokeInitMethods()调用自定义的init方法,Java反射技术
6.4.applyBeanPostProcessorsAfterInitialization()在初始化方法之后执行处理(增强)
7.正常使用我们初始化好的这个Bean对象
8.销毁bean

本篇幅主要讲上一篇Spring容器刷新时的refresh()中的
finishBeanFactoryInitialization(beanFactory);这个方法的整体逻辑是初始化所有剩余的单例Bean。里面我们具体看beanFactory.preInstantiateSingletons();这个方法。对配置了lazy-init属性的单态模式Bean进行预实例化处理。

//对配置lazy-init属性单态Bean的预实例化
	@Override
	public void preInstantiateSingletons() throws BeansException {
		if (this.logger.isDebugEnabled()) {
			this.logger.debug("Pre-instantiating singletons in " + this);
		}

		// Iterate over a copy to allow for init methods which in turn register new bean definitions.
		// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

		// Trigger initialization of all non-lazy singleton beans...
		for (String beanName : beanNames) {
	    // Bean定义公共的抽象类是AbstractBeanDefinition,普通的Bean在Spring加载Bean定义的时候,实例化出来的是GenericBeanDefinition
		// 而Spring上下文包括实例化所有Bean用的AbstractBeanDefinition是RootBeanDefinition
		// 这时候就使用getMergedLocalBeanDefinition方法做了一次转化,将非RootBeanDefinition转换为RootBeanDefinition以供后续操作。
		// 注意如果当前BeanDefinition存在父BeanDefinition,会基于父BeanDefinition生成一个RootBeanDefinition,然后再将调用OverrideFrom子BeanDefinition的相关属性覆写进去。
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			//Bean不是抽象的,是单态模式的,且lazy-init属性配置为false
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				//如果指定名称的bean是创建容器的Bean
				if (isFactoryBean(beanName)) {
					//FACTORY_BEAN_PREFIX=”&”,当Bean名称前面加”&”符号
					//时,获取的是产生容器对象本身,而不是容器产生的Bean.
					//调用getBean方法,触发容器对Bean实例化和依赖注入过程
					final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
					//标识是否需要预实例化
					boolean isEagerInit;
					if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
						//一个匿名内部类
						isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>) () ->
								((SmartFactoryBean<?>) factory).isEagerInit(),
								getAccessControlContext());
					}
					else {
						isEagerInit = (factory instanceof SmartFactoryBean &&
								((SmartFactoryBean<?>) factory).isEagerInit());
					}
					if (isEagerInit) {
						//调用getBean方法,触发容器对Bean实例化和依赖注入过程
						getBean(beanName);
					}
				}
				else {
					getBean(beanName);
				}
			}
		}

上述代码的逻辑是遍历初始化所有非懒加载单例Bean。本质用的是java的反射通过构造器进行创建实例。如果不是FactoryBean的具体实现的话,我们会走getBean(beanName);这部分逻辑。主要处理逻辑的AbstractBeanFactory的doGetBean()方法。我们这里主要探讨单实例的bean。只看主要逻辑,其他的校验暂时不看。

// Create bean instance.
				//创建单例模式Bean的实例对象
				if (mbd.isSingleton()) {
					//这里使用了一个匿名内部类,创建Bean实例对象,并且注册给所依赖的对象
					sharedInstance = getSingleton(beanName, () -> {
						try {
							//创建一个指定Bean实例对象,如果有父级继承,则合并子类和父类的定义
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
					
							//显式地从容器单例模式Bean缓存中清除实例对象
							destroySingleton(beanName);
							throw ex;
						}
					});
					//获取给定Bean的实例对象
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}

主要创建bean的逻辑在getSingleton的方法里面。该方法第二个参数为函数式接口。会在getSingleton的方法里面进行调用。主要实现逻辑在AbstractAutowireCapableBeanFactory的createBean()方法。然后调用doCreateBean()。

//真正创建Bean的方法
	protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {

		// Instantiate the bean.
		//封装被创建的Bean对象
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		final Object bean = instanceWrapper.getWrappedInstance();
		//获取实例化对象的类型
		Class<?> beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) {
			mbd.resolvedTargetType = beanType;
		}
		//调用PostProcessor后置处理器
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				try {
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				mbd.postProcessed = true;
			}
		}

	     // 这个时候很重要,会向二级缓存的map添加bean的名称和创建工厂。解决循环依赖的时候要使用。
		//向容器中缓存单例模式的Bean对象,以防循环引用
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isDebugEnabled()) {
				logger.debug("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			//这里是一个匿名内部类,为了防止循环引用,尽早持有对象的引用
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		//Bean对象的初始化,依赖注入在此触发
		//这个exposedObject在初始化完成之后返回作为依赖注入完成后的Bean
		Object exposedObject = bean;
		try {
			//将Bean实例对象封装,并且Bean定义中配置的属性值赋值给实例对象
			populateBean(beanName, mbd, instanceWrapper);
			//初始化Bean对象
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		catch (Throwable ex) {
			if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
				throw (BeanCreationException) ex;
			}
			else {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
			}
		}

    //	、、、、、、省略部分代码
		return exposedObject;
	}

上述代码中有三个方法比较重要。
1、createBeanInstance(beanName, mbd, args);调用反射或者使用工厂方法对Bean进行实例化。
2、populateBean(beanName, mbd, instanceWrapper); 将Bean实例对象封装,并且Bean定义中配置的属性值赋值给实例对象。这里面也会判断属性赋值时是不是依赖于创建别的bean,也是解决循环依赖的处理逻辑。
3、initializeBean(beanName, exposedObject, mbd);初始化Bean对象,在初始化bean的时候,会调用各种后置处理器,进行处理所需要的逻辑。比如
BeanPostProcessor后置处理器的postProcessBeforeInitialization,回调方法的调用,为Bean实例初始化前做一些处理。
BeanPostProcessor后置处理器的postProcessAfterInitialization,为Bean实例初始化之后做一些处理。

三、总结

本篇幅主要讲解了Spring容器在初始化普通bean的流程。从实例化一个bean对象,到属性赋值,三级缓存来解决循环依赖的问题,在到初始化前后的后置处理器的调用,讲解了整个bean的生命周期的流程。
下一篇我们主要讲解下Spring Aop的调用源码解析。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值