Spring IOC源码:finishBeanFactoryInitialization详解
创始人
2024-02-10 19:04:46
0

前言

这篇文章开始讲解Bean的实例化过程,也就是refresh中的finishBeanFactoryInitialization方法,该方法是IOC中最核心也是最复杂的,后续会分为几篇文章进行详细讲解。该方法会将beanFactory工厂中的定义信息进行实例化及属性注入;

正文

进入fresh中的finishBeanFactoryInitialization方法

	protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {// 判断beanFactory工厂中是否有ConversionService或其定义信息,没有则实例化创建一个ConversionService转换器if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {beanFactory.setConversionService(beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));}// Register a default embedded value resolver if no bean post-processor// (such as a PropertyPlaceholderConfigurer bean) registered any before:// at this point, primarily for resolution in annotation attribute values.//如果工厂中没有嵌入式解析器,则创建一个默认的if (!beanFactory.hasEmbeddedValueResolver()) {beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));}// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.//实例化LoadTimeWeaverAware对象String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);for (String weaverAwareName : weaverAwareNames) {getBean(weaverAwareName);}// Stop using the temporary ClassLoader for type matching.beanFactory.setTempClassLoader(null);// Allow for caching all bean definition metadata, not expecting further changes.//冻结bean定义信息,不允许bean定义信息被修改,因为要开始实例化了beanFactory.freezeConfiguration();// 实例化剩余的懒加载的beanbeanFactory.preInstantiateSingletons();}

beanFactory.preInstantiateSingletons(),见方法1详解

方法1:preInstantiateSingletons

public void preInstantiateSingletons() throws BeansException {if (logger.isTraceEnabled()) {logger.trace("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.//复杂一份新的beanName用于遍历,因为bean中的init方法可能会创建新的bean定义信息List beanNames = new ArrayList<>(this.beanDefinitionNames);// Trigger initialization of all non-lazy singleton beans...//遍历所有非懒加载beanNamefor (String beanName : beanNames) {//该bean可能存在父类定义,这里合并后封装成RootBeanDefinition 对象,后续操作都是使用RootBeanDefinition RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);//不是抽象、且非懒加载的单例if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {//判断是否的factoryBeanif (isFactoryBean(beanName)) {//获取factoryBean本对象,这里如果beanName带&前缀的话获取的是FactoryBean对象,如果是不带前缀的beanName,则获取的是FactoryBean中的getObject返回的实例。Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);if (bean instanceof FactoryBean) {final FactoryBean factory = (FactoryBean) bean;//用于标识是否是急切初始化boolean isEagerInit;if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {isEagerInit = AccessController.doPrivileged((PrivilegedAction)((SmartFactoryBean) factory)::isEagerInit,getAccessControlContext());}else {//如果实现了SmartFactoryBean 接口,则该Bean会提前进行创建isEagerInit = (factory instanceof SmartFactoryBean &&((SmartFactoryBean) factory).isEagerInit());}//如果是急切初始化,提前进行生成if (isEagerInit) {getBean(beanName);}}}else {//非FactoryBean,直接实例化BeangetBean(beanName);}}}// Trigger post-initialization callback for all applicable beans...//遍历所有的Bean,如果为SmartInitializingSingleton类型,则调用其afterSingletonsInstantiated方法。for (String beanName : beanNames) {//从一级缓存中获取对象Object singletonInstance = getSingleton(beanName);if (singletonInstance instanceof SmartInitializingSingleton) {final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;if (System.getSecurityManager() != null) {AccessController.doPrivileged((PrivilegedAction) () -> {smartSingleton.afterSingletonsInstantiated();return null;}, getAccessControlContext());}else {smartSingleton.afterSingletonsInstantiated();}}}}
 

1、FactoryBean翻译过来就是工厂bean的意思,它跟我们平时在配置文件中配置的bean有一点区别,平常的bean或者getBean方法中以反射的形式进行创建,而实现了FactoryBean接口的Bean会通过其getObject方法返回一个实例。如:

public class MyFactoryBean implements FactoryBean {@Overridepublic Object getObject() throws Exception {Student student=new Student();return student;}@Overridepublic Class getObjectType() {return Student.class;}
}

假如该工厂bean的beanName为myFactoryBean,当我们传入myFactoryBean去获取Bean的时候返回的其实是Student对象,如果传入的是带前缀的&myFactoryBean,则返回的是MyFactoryBean 本身这个实例。

2、在整个IOC中我们经常会看到getBean(beanName)方法,其参数是一个beanName。该方法是将beanFactory工厂中的定义信息进行实例化的节点,传入beanName,会先从缓存中查询是否存在,存在则返回,不存在则会进行创建。

getMergedLocalBeanDefinition(beanName),见方法2详解
isFactoryBean(beanName),见方法5详解

方法2:getMergedLocalBeanDefinition

	protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {// 从缓存中查询是否存在该定义信息RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);if (mbd != null && !mbd.stale) {return mbd;}return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));}
	protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)throws BeanDefinitionStoreException {return getMergedBeanDefinition(beanName, bd, null);}

getMergedBeanDefinition(beanName, bd, null),见方法3详解

方法3:getMergedBeanDefinition

protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)throws BeanDefinitionStoreException {synchronized (this.mergedBeanDefinitions) {RootBeanDefinition mbd = null;RootBeanDefinition previous = null;// Check with full lock now in order to enforce the same merged instance.if (containingBd == null) {//尝试从缓存中获取mbd = this.mergedBeanDefinitions.get(beanName);}if (mbd == null || mbd.stale) {previous = mbd;mbd = null;//判断该bean是否存在父类,如果没有则判断本身是否是RootBeanDefinition,否则创建一个新的RootBeanDefinitionif (bd.getParentName() == null) {// Use copy of given root bean definition.//一般BeanDefinition在被加载后是GenericBeanDefinition或ScannedGenericBeanDefinitionif (bd instanceof RootBeanDefinition) {mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();}else {mbd = new RootBeanDefinition(bd);}}else {// Child bean definition: needs to be merged with parent.BeanDefinition pbd;try {//获取父类名称String parentBeanName = transformedBeanName(bd.getParentName());//如果父类与当前beanName不一致,则递归调用当前方法进行查找合并,因为父类也有可能存在父类。。if (!beanName.equals(parentBeanName)) {pbd = getMergedBeanDefinition(parentBeanName);}else {//获取父类的BeanFactory BeanFactory parent = getParentBeanFactory();//只有在存在父BeanFactory的情况下,才允许父定义beanName与自己相同,否则就是将自己设置为父定义if (parent instanceof ConfigurableBeanFactory) {pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);}else {throw new NoSuchBeanDefinitionException(parentBeanName,"Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +"': cannot be resolved without an AbstractBeanFactory parent");}}}catch (NoSuchBeanDefinitionException ex) {throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,"Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);}// Deep copy with overridden values.//创建新的,并覆盖原来的RootBeanDefinitionmbd = new RootBeanDefinition(pbd);//设置被覆盖的bean定义mbd.overrideFrom(bd);}// Set default singleton scope, if not configured before.//如果没有配置Scope属性,则默认按单例处理if (!StringUtils.hasLength(mbd.getScope())) {mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON);}// A bean contained in a non-singleton bean cannot be a singleton itself.// Let's correct this on the fly here, since this might be the result of// parent-child merging for the outer bean, in which case the original inner bean// definition will not have inherited the merged outer bean's singleton status.if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {//同步Scope属性值mbd.setScope(containingBd.getScope());}// Cache the merged bean definition for the time being// (it might still get re-merged later on in order to pick up metadata changes)if (containingBd == null && isCacheBeanMetadata()) {//存储到缓存中this.mergedBeanDefinitions.put(beanName, mbd);}}//如果原先的定义信息不为空,则拷贝部分先前的属性值到当前的合并的定义中if (previous != null) {copyRelevantMergedBeanDefinitionCaches(previous, mbd);}return mbd;}}

这里稍微整理一下:
1、如果当前的bean定义不存在父类,则判断当前定义是否为RootBeanDefinition,如果是则直接返回,不是则创建一个新的合并的Bean定义信息(RootBeanDefinition)。

2、如果存在父定义,并且父定义beanName与子定义信息的beanName不同时,则递归创建RootBeanDefinition,因为父类也存在父类,即子类有父类,爷爷类,太爷爷类。。。

3、如果父定义的beanName与自定义的beanName相同时,如果其父工厂为ConfigurableBeanFactory类型,则调用父工厂getMergedBeanDefinition方法,从父工厂中进行查找合并。

transformedBeanName(bd.getParentName()),见方法4详解

方法4:transformedBeanName

	protected String transformedBeanName(String name) {return canonicalName(BeanFactoryUtils.transformedBeanName(name));}
	public static String transformedBeanName(String name) {Assert.notNull(name, "'name' must not be null");//如果名称带不以&符号开头则直接返回if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {return name;}//切割&符号后面的字符为beanNamereturn transformedBeanNameCache.computeIfAbsent(name, beanName -> {do {beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());}while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));return beanName;});}
	public String canonicalName(String name) {String canonicalName = name;// Handle aliasing...String resolvedName;do {//从别名缓存中获取真正的beanNameresolvedName = this.aliasMap.get(canonicalName);if (resolvedName != null) {canonicalName = resolvedName;}}while (resolvedName != null);return canonicalName;}

方法5:isFactoryBean

	public boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException {//去除&前缀,通过别名获取beanNameString beanName = transformedBeanName(name);//尝试从缓存中获取Object beanInstance = getSingleton(beanName, false);if (beanInstance != null) {//判断是否实现了FactoryBean接口return (beanInstance instanceof FactoryBean);}//如果bean定义缓存中没有存在该beanName 并且 其父类工厂是一个ConfigurableBeanFactoryif (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {// 从父工厂中寻找return ((ConfigurableBeanFactory) getParentBeanFactory()).isFactoryBean(name);}return isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName));}

整理下思路:
1、先将beanName去掉前缀,并尝试从别名缓存获取对应的beanName,通过beanName在三级缓存中查询是否已经实例化的对象,有则进行类型判断。

2、beanName在当前beanFactory中没有存在定义,并且该工厂存在父工厂且是ConfigurableBeanFactory类型,则在父工厂进行查找,也就是使用父工厂重新执行一遍isFactoryBean流程。

3、beanName在当前beanFactory工厂中存在定义,则进行解析判断。

getSingleton(beanName, false),见方法6详解

isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName)),见方法7详解

方法6:getSingleton

	protected Object getSingleton(String beanName, boolean allowEarlyReference) {//从一级缓存中获取,即成品缓存(完成了初始化过程即属性注入等)Object singletonObject = this.singletonObjects.get(beanName);//如果一级缓存获取不到,且在创建的缓存中存在时if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {synchronized (this.singletonObjects) {//从二级缓存中获取,即半成品缓存(完成了初始化,未实例化)singletonObject = this.earlySingletonObjects.get(beanName);//二级缓存中不存在,并且允许提前引用if (singletonObject == null && allowEarlyReference) {//从三级缓存中获取ObjectFactory对象ObjectFactory singletonFactory = this.singletonFactories.get(beanName);if (singletonFactory != null) {//调用getObject获取实例,该实例也是半成品singletonObject = singletonFactory.getObject();//放入到二级缓存中this.earlySingletonObjects.put(beanName, singletonObject);//从三级缓存中移除this.singletonFactories.remove(beanName);}}}}return singletonObject;}

这个方法很重要,是解决循环依赖的组成部分。singletonObjects一级缓存、earlySingletonObjects二级缓存、singletonFactories三级缓存。这里简单介绍下循环依赖,现有A、B两个类,A中有B属性,B中也有A属性,当创建A后,对属性B进行注入时,会去创建B,对B进行属性注入时发现B中需要注入A属性,就会再创建A,这样就死循环了。

我们是否可以使用一级缓存解决循环依赖呢?
A实例化完成时,放入一级缓存中,当属性注入时去一级缓存中寻找B,找不到则创建B;实例化B后,放入一级缓存中,在对B进行属性注入时,从一级缓存中寻找A,找到后进行注入,这时候A再拿到B进行属性注入。这种方式也可以解决循环依赖,但是如果存在多线程,并且在创建过程中去获取A,而A此时的状态还是半成品,那就有问题了,而且如果A的AOP代理对象,那完全操作不了。

是否可以使用二级缓存解决循环依赖呢?
创建A后,放入二级缓存中,并从二级缓存查找B,找不到则创建B,B创建完成后放入二级缓存中,从二级缓存中查找A进行属性注入,这时候的B就是一个完整品,将其放入一级缓存中,再从二级缓存中移除。A从一级缓存中获取B,进行属性注入后,加入一级缓存,并且移除二级缓存中的半成品。有了二级缓存后,就可以解决多线程获取的问题。但是如果A被AOP进行代理,A刚开始创建时肯定是一个原始对象(未被代理的),所以B在进行属性注入时从二级缓存中拿出来的注入的对象就是未被代理的A了,那这样也有问题了。

三级缓存解决循环依赖:
创建A后,我们往三级缓存中存入ObjectFactory类型的包装类A,此getObject方法实现如下代码所示(会提前调用AOP代理生成代理对象);属性注入时,会创建B,B会往三级缓存中存入ObjectFactory类型的包装类B,进行属性注入时,从一级缓存中获取A,取不到从二级中缓存,取不到从三级缓存获取,调用getObject方法获取代理后的A对象,并存入二级缓存中,移除三级缓存数据,此时B对象就是一个完整的对象,并且其属性A也是一个代理后的对象,加入一级缓存,移除二级缓存(如果B还有引用其它属性如C,C中也引用了B时,会存在数据)、三级缓存。此时A获取到B对象后进行注入,添加到一级缓存中,并移除二级缓存、三级缓存数据。

	protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {Object exposedObject = bean;if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);}}}return exposedObject;}

方法7:isFactoryBean

	protected boolean isFactoryBean(String beanName, RootBeanDefinition mbd) {//判断是否是FactoryBeanBoolean result = mbd.isFactoryBean;if (result == null) {//获取class对象Class beanType = predictBeanType(beanName, mbd, FactoryBean.class);//判断是否是FactoryBean或其子类实现result = (beanType != null && FactoryBean.class.isAssignableFrom(beanType));mbd.isFactoryBean = result;}return result;}

总结

本篇文章讲解了bean创建前的准备工作,及其FactoryBean的概念,并且讲解了三级缓存的作用。

一级缓存 singletonObjects:存放完整的Bean对象

二级缓存 earlySingletonObjects:存放半成品Bean对象

三级缓存singletonFactories:存放封装后的ObjectFactory,通过getObject返回实例对象,该对象可能是代理后的对象也可能是普通对象。

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
客厅放八骏马摆件可以吗(家里摆... 今天给各位分享客厅放八骏马摆件可以吗的知识,其中也会对家里摆八骏马摆件好吗进行解释,如果能碰巧解决你...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...