【spring学习笔记 五】finishBeanFactoryInitialization()


前几篇我们聊完了Bean初始化的前置步骤,也就是后面各个节点的处理器已经准备完毕了,下面就等着人去触发它们了。
这一篇我们就一起来看看,各个节点都分别在怎么样的一个时间上面执行。

preInstantiateSingletons()

这个方法就是实例化单例对象的入口,

它的内部可以看成两步:

  1. 初始化所有单例对象
  2. 唤醒SmartInitializingSingleton接口的方法

这里也可以看出,如果你需要在所有单例都创建完毕之后去做一些事情可以去实现SmartInitializingSingleton。

初始化所有单例对象

我还是拆分细点讲,如果上来就一大段代码,估计各位同学会瞬间失去耐心。

实例化也分成了两步,

  1. 对于实现了FactoryBean的实例化
  2. 普通Bean的实例化
		for (String beanName : beanNames) {
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			//非抽象,单例,非延迟加载
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				if (isFactoryBean(beanName)) {...}
				else {getBean(beanName);}
			}
		

FactoryBean的实例化

这个接口的作用是什么呢?其实它相当于一个小型的Bean工厂,给开发者提供一种更便捷的方式创建Bean。
比如说,你这个Bean有些东西需要通过查询数据库才能组装好,这时候就可以用这个接口,在内部通过编码的方式组装你的Bean。
Spring对于实现了FactoryBean的类所对应的实例,在BeanFactory中的name是"&"+beanName。
例如这样

public class TestFactoryBean implements FactoryBean<T>

那么BeanFactory中的name存放的就是“&TestFactoryBean”,如果我们通过“TestFactoryBean”这个名称去BeanFactory中获取,将会调用其getObject方法。

所以这里对FactoryBean要进行处理,在name前面添加一个&符号,然后在访问getBean方法创建Bean,也就是说最终会和创建普通Bean的实例流程保持一致。

普通Bean的实例化 (doGetBean)

接下来我们来看下普通Bean的实例化流程

  1. 通过beanName获取单例对象
  2. 如果存在则,判断是否是FactoryBean,如果是则返回getObject,否则返回它本身。
  3. 如果不存在,则实例化。
  4. 对创建的实例类型与需求的类型进行比较,不匹配则抛出异常
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null){
			...
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}
		else {...}
		if (requiredType != null && !requiredType.isInstance(bean)){...}
		return (T)bean;

我们着重关注下第三步

  1. 自身是否有父BeanFactory,如果有则通过父BeanFactory加载。
  2. 检测当前bean是否有@DependsOn注解,如果有,先加载注解中的Bean。
  3. 根据Scope进行实例化(本篇文章与后续文章只分析单例模式,原型和其它模式各位同学可以自行去学习)
			//如果有父类工厂,并且自身的BeanDefinition不包含,则通过父类进行加载
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)){...}
			//获取当前Bean需要在某个Bean实例化之后才实例化
			//通过注解@DependsOn来控制,不能在@DependsOn中相互写对方,会直接抛出异常,因为会导致这段代码死循环
			String[] dependsOn = mbd.getDependsOn();
			if (dependsOn != null) {...}
			//单例模式
			if (mbd.isSingleton()){...}
			//原型模式
			else if (mbd.isPrototype())
			//其它模式
			else {...}

其中单例模式

				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, () -> {
						try { 
							//创建bean
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							// Explicitly remove instance from singleton cache: It might have been put there
							// eagerly by the creation process, to allow for circular reference resolution.
							// Also remove any beans that received a temporary reference to the bean.
							destroySingleton(beanName);
							throw ex;
						}
					});
					//应该很熟悉,判断是否是FactoryBean 并返回对应实例
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}

由于getSingleton内部都是一些判断,我们这里就直接分析createBean的内部流程。

createBean()

在创建Bean内部分为了两步,

  1. 通过特殊手段创建Bean并返回
  2. 通过正常手段创建Bean并返回
			//步骤一
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			if (bean != null) {
				return bean;
			}
			...
			//步骤二 看过源码的应该比较熟悉这个方法doCreateBean
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
			if (logger.isTraceEnabled()) {
				logger.trace("Finished creating instance of bean '" + beanName + "'");
			}
			return beanInstance;

接下来我们就来看看这步骤一究竟怎么个特殊法。

其实就是找到所有实现了InstantiationAwareBeanPostProcessor的方法(其继承于BeanPostProcessor),然后唤醒postProcessBeforeInstantiation()方法,如果有返回值,就以返回值作为Bean装载到BeanFactory中。
然后访问BeanPostProcess的后置方法postProcessAfterInitialization()

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
		Object bean = null;
		if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
			// Make sure bean class is actually resolved at this point.
			//没有访问BeanPostProcessor的Before方法?
			if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
				Class<?> targetType = determineTargetType(beanName, mbd);
				if (targetType != null) {
					//访问所有的InstantiationAwareBeanPostProcessor 如果返回了结果则直接返回
					bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
					if (bean != null) {
						//唤醒BeanPostProcessor后置方法
						bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
					}
				}
			}
			mbd.beforeInstantiationResolved = (bean != null);
		}
		return bean;
	}

异常手段看完了,接下来等我们下一章在来聊聊正常手段创建Bean。

唤醒SmartInitializingSingleton实例的方法

当所有单例对象都创建完毕之后,就会去容器中查找所有实现了SmartInitializingSingleton接口的实例,并访问其afterSingletonsInstantiated方法。

(某些同学可能使用过InitializingBean这个接口,但是你要明白,你在初始化的时候有可能其它的Bean并没有实例化完毕,所以有些操作是有风险的,如果你分不清这时间点到底对不对,保险的方式就是使用SmartInitializingSingleton这个接口)

		for (String beanName : beanNames) {
			Object singletonInstance = getSingleton(beanName);
			if (singletonInstance instanceof SmartInitializingSingleton) {
				final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
						smartSingleton.afterSingletonsInstantiated();
						return null;
					}, getAccessControlContext());
				}
				else {
					smartSingleton.afterSingletonsInstantiated();
				}
			}
		}

总结

也不知道说些什么,最近又是些糟心的事。 那就新年快了吧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

唐芬奇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值