• Spring Ioc源码分析系列--Bean实例化过程(一)


    Spring Ioc源码分析系列--Bean实例化过程(一)

    前言

    上一篇文章Spring Ioc源码分析系列--Ioc容器注册BeanPostProcessor后置处理器以及事件消息处理已经完成了对IoC容器启动方法也就是refresh()方法的简单分析。但是之前的分析在对容器实例化Bean的过程的略过了,留到了这后续的文章分析,所以这篇文章会对Bean的实例化过程做一个介绍。

    首先来理一下本文的思路:关键词是实例化。由于Spring是利用反射实现的实例化,脑子里先简单想一下Java里利用发射实例化一个对象需要哪些步骤和操作。毫无疑问,我们首先要知道对象的class,接着需要确定使用什么构造函数以及确定构造函数的参数等。利用这些已经基本可以实现一个对象的实例化,当然实际上需要的东西可能更多更复杂,这里只是举个例子。那么需要的这些信息可以去哪里提取呢?对Spring有了解的可能都马上能想到BeanDefinition,这是一份原料表,里面有我们构造一个实例化对象所需的所有参数。如果不太理解这个定义,可以参考一下上篇文章的例子。

    如果不清楚BeanDefinition是从哪里来的以及不清楚如何定义的,可以参考之前的文章Spring Ioc源码分析系列--Ioc源码入口分析的关键实现系列方法 loadBeanDefinitions ()。这篇文章讲解注册的时候只是说了注册到容器里,并没有说明具体是注册到了哪里,这里点明一下,所谓讲BeanDefinition注册到容器里,就是将BeanDefinition放入到容器的一个Map里,具体是注册到了DefaultListableBeanFactorybeanDefinitionMap属性里,beanName会保存到beanDefinitionNames属性里,这是个list集合,里面的beanName会保持注册时候的顺序。

    实例化的开始就是从遍历所有的beanName开始,话不多说,开始分析吧。

    源码分析

    bean实例化入口

    还记得实例化入口的方法名吗?回忆一下,算了,反正也不会有人记得。是beanFactory.preInstantiateSingletons(),具体实现是在DefaultListableBeanFactory类里。

    跟进代码查看,可以看到,这段代码分为两部分,第一个for循环用于先实例化对象,第二个for循环完成一些实例化之后的回调操作。我们先来看第一个for循环,首先是遍历所有的beanNames获取BeanDefinition,然后根据工厂bean非工厂bean进行相应处理,最后调用getBean(beanName)实例化对象。注意这里实例化的是非抽象的、单例的并且是非懒加载的bean,这个前提非常重要。

    	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.
    		// 所有bd的名称
    		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
    
    		// Trigger initialization of all non-lazy singleton beans...
    		// 遍历所有bd,一个个进行创建
    		for (String beanName : beanNames) {
    			// 获取到指定名称对应的bd
    			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
    			// 对不是延迟加载的单例的Bean进行创建
    			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
    				// 判断是否是一个FactoryBean
    				if (isFactoryBean(beanName)) {
    					// 如果是一个factoryBean的话,先创建这个factoryBean,创建factoryBean时,需要在beanName前面拼接一个&符号
    					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<Boolean>)
    											((SmartFactoryBean<?>) factory)::isEagerInit,
    									getAccessControlContext());
    						}
    						else {
    							// 判断是否是一个SmartFactoryBean,并且不是懒加载的,就意味着,在创建了这个factoryBean之后要立马调用它的getObject方法创建另外一个Bean
    							isEagerInit = (factory instanceof SmartFactoryBean &&
    									((SmartFactoryBean<?>) factory).isEagerInit());
    						}
    						if (isEagerInit) {
    							getBean(beanName);
    						}
    					}
    				}
    				else {
    					// 不是factoryBean的话,我们直接创建就行了
    					getBean(beanName);
    				}
    			}
    		}
    
    		// Trigger post-initialization callback for all applicable beans...
    		// 在创建了所有的Bean之后,遍历为所有适用的 bean 触发初始化后回调,也就是这里会对延迟初始化的bean进行加载...
    		for (String beanName : beanNames) {
    			// 这一步其实是从缓存中获取对应的创建的Bean,这里获取到的必定是单例的
    			Object singletonInstance = getSingleton(beanName);
    			// 判断是否是一个SmartInitializingSingleton,
    			// 最典型的就是我们之前分析过的EventListenerMethodProcessor,
    			// 在这一步完成了对已经创建好的Bean的解析,会判断其方法上是否有 @EventListener注解,
    			// 会将这个注解标注的方法通过EventListenerFactory转换成一个事件监听器并添加到监听器的集合中
    			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();
    				}
    			}
    		}
    	}
    

    获取BeanDefinition

    首先跟进getMergedLocalBeanDefinition(beanName)方法,这里首先会尝试从mergedBeanDefinitions里去获取,这个mergedBeanDefinitions存放着已经合并过的BeanDefinition,获取不到再真正调用getMergedBeanDefinition(beanName, getBeanDefinition(beanName))去获取。

    	/**
    	 * Return a merged RootBeanDefinition, traversing the parent bean definition
    	 * if the specified bean corresponds to a child bean definition.
    	 *
    	 * 返回一个合并的 RootBeanDefinition,如果指定的 bean 对应于子 bean 定义,则遍历父 bean 定义。
    	 *
    	 * @param beanName the name of the bean to retrieve the merged definition for
    	 * @return a (potentially merged) RootBeanDefinition for the given bean
    	 * @throws NoSuchBeanDefinitionException if there is no bean with the given name
    	 * @throws BeanDefinitionStoreException in case of an invalid bean definition
    	 */
    	protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
    		// Quick check on the concurrent map first, with minimal locking.
    		// 首先检查 mergedBeanDefinitions ,最小程度影响并发性能
    		RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
    		if (mbd != null && !mbd.stale) {
    			return mbd;
    		}
    		return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
    	}
    

    先看getBeanDefinition(beanName),这个方法就是简单的去beanDefinitionMap里获取BeanDefinition,如果获取不到,就抛出异常。beanDefinitionMap就是上面说到的BeanDefinition存放的地方。

    	public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
    		BeanDefinition bd = this.beanDefinitionMap.get(beanName);
    		if (bd == null) {
    			if (logger.isTraceEnabled()) {
    				logger.trace("No bean named '" + beanName + "' found in " + this);
    			}
    			throw new NoSuchBeanDefinitionException(beanName);
    		}
    		return bd;
    	}
    

    接下来就进入到getMergedBeanDefinition()方法获取BeanDefinition,为啥要从beanDefinitionMap获取了还进行一个merged获取呢?这是因为Bean有层次关系,子类需要合并父类的属性方法等,所以要进行一次合并,合并完成后会放入到mergedBeanDefinitions里,功能和属性名区分度还是十分贴切的🐕。

    跟进方法,代码已添加注释,比较简单,跟着看看就行。

    	/**
    	 * Return a RootBeanDefinition for the given top-level bean, by merging with
    	 * the parent if the given bean's definition is a child bean definition.
    	 *
    	 * 如果给定 bean 的定义是子 bean 定义,则通过与父级合并返回给定顶级 bean 的 RootBeanDefinition。
    	 *
    	 * @param beanName the name of the bean definition
    	 * @param bd the original bean definition (Root/ChildBeanDefinition)
    	 * @return a (potentially merged) RootBeanDefinition for the given bean
    	 * @throws BeanDefinitionStoreException in case of an invalid bean definition
    	 */
    	protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
    			throws BeanDefinitionStoreException {
    
    		return getMergedBeanDefinition(beanName, bd, null);
    	}
    
    	/**
    	 * Return a RootBeanDefinition for the given bean, by merging with the
    	 * parent if the given bean's definition is a child bean definition.
    	 *
    	 * 如果给定 bean 的定义是子 bean 定义,则通过与父合并返回给定 bean 的 RootBeanDefinition
    	 *
    	 * @param beanName the name of the bean definition
    	 * @param bd the original bean definition (Root/ChildBeanDefinition)
    	 * @param containingBd the containing bean definition in case of inner bean,
    	 * or {@code null} in case of a top-level bean
    	 *    如果是内部 bean,则包含 bean 定义,如果是顶级 bean,则为 {@code null}
    	 * @return a (potentially merged) RootBeanDefinition for the given bean
    	 * @throws BeanDefinitionStoreException in case of an invalid bean definition
    	 */
    	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;
    				if (bd.getParentName() == null) {
    					// Use copy of given root bean definition.
    					// 使用给定根 bean 定义的副本。
    					if (bd instanceof RootBeanDefinition) {
    						mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
    					}
    					else {
    						mbd = new RootBeanDefinition(bd);
    					}
    				}
    				else {
    					// Child bean definition: needs to be merged with parent.
    					// 子bean定义:需要与父合并。
    					BeanDefinition pbd;
    					try {
    						String parentBeanName = transformedBeanName(bd.getParentName());
    						if (!beanName.equals(parentBeanName)) {
    							pbd = getMergedBeanDefinition(parentBeanName);
    						}
    						else {
    							BeanFactory parent = getParentBeanFactory();
    							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.
    					// 具有覆盖值的深拷贝。
    					mbd = new RootBeanDefinition(pbd);
    					mbd.overrideFrom(bd);
    				}
    
    				// Set default singleton scope, if not configured before.
    				// 如果之前未配置,则设置默认单例范围。
    				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.
    				// 包含在非单例 bean 中的 bean 本身不能是单例。
    				// 让我们在这里即时纠正这个问题,因为这可能是外部 bean 的父子合并的结果,
    				// 在这种情况下,原始内部 bean 定义将不会继承合并的外部 bean 的单例状态。
    				if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
    					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)
    				// 暂时缓存合并的 bean 定义(它可能稍后仍会重新合并以获取元数据更改)
    				if (containingBd == null && isCacheBeanMetadata()) {
    					this.mergedBeanDefinitions.put(beanName, mbd);
    				}
    			}
    			if (previous != null) {
    				copyRelevantMergedBeanDefinitionCaches(previous, mbd);
    			}
    			return mbd;
    		}
    

    创建Bean

    获取BeanDefinition完成后,接下来就调用getBean(beanName)进行bean的实例化了。当然这里的创建还是分了工厂Bean和非工厂Bean两个逻辑,如果是一个工厂Bean,那么getBean(beanName)这一步只会创建一个工厂Bean,接下来会通过isEagerInit参数判断是否需要初始化工厂Bean的对象,如果需要,再调用getBean(beanName)去立马获取工厂Bean需要生产的对象。不是工厂Bean的话,直接一步到位创建对象了,少一分曲折。

    跟进代码查看,可以看到真正的执行代码的是在doGetBean()方法里。跟进doGetBean()方法,发现代码非常的长,这里我会把这个方法切分成几块去解析。

    	public Object getBean(String name) throws BeansException {
    		return doGetBean(name, null, null, false);
    	}
    

    由于代码量比较大,这里贴一张图,展示各个部分间的作用,然后对每个部分进行逐步分析。

    1653547332139

    看起来是不是很简单,其实每一部分都包含了大量的细节操作,先来看第一步的名称转换,这个比较简单。

    名称转换

    这一步就是把&开头的name转换成不带&name

    	/**
    	 * Return the bean name, stripping out the factory dereference prefix if necessary,
    	 * and resolving aliases to canonical names.
    	 *
    	 * 返回 bean 名称,必要时去除工厂取消引用前缀,并将别名解析为规范名称。
    	 *
    	 * @param name the user-specified name
    	 * @return the transformed bean name
    	 */
    	protected String transformedBeanName(String name) {
    		return canonicalName(BeanFactoryUtils.transformedBeanName(name));
    	}
    

    可以看到这里会有个循环去处理,带有多个&的都会被去掉。

    	/**
    	 * Return the actual bean name, stripping out the factory dereference
    	 * prefix (if any, also stripping repeated factory prefixes if found).
    	 *
    	 * 返回实际的 bean 名称,去除工厂取消引用前缀(如果有,也去除重复的工厂前缀,如果找到)。
    	 *
    	 * @param name the name of the bean
    	 * @return the transformed name
    	 * @see BeanFactory#FACTORY_BEAN_PREFIX
    	 */
    	public static String transformedBeanName(String name) {
    		Assert.notNull(name, "'name' must not be null");
    		if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
    			return name;
    		}
    		return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
    			do {
    				beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
    			}
    			while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
    			return beanName;
    		});
    	}
    

    确定名称,一个Bean可能会有很多委派的别名,这个时候需要确定最根本的那个name,用这个最根本的name来作为beanName去进行后续的操作,这里同样有个循环去处理,因为别名也会有多重,会存在别名的别名这种情况。

    	/**
    	 * Determine the raw name, resolving aliases to canonical names.
    	 * 确定原始名称,将别名解析为规范名称。
    	 * @param name the user-specified name
    	 * @return the transformed name
    	 */
    	public String canonicalName(String name) {
    		String canonicalName = name;
    		// Handle aliasing...
    		// 处理别名...
    		String resolvedName;
    		do {
    			// 可能会有别名层层嵌套的情况,所以需要获取到最终的名称
    			resolvedName = this.aliasMap.get(canonicalName);
    			if (resolvedName != null) {
    				canonicalName = resolvedName;
    			}
    		}
    		while (resolvedName != null);
    		return canonicalName;
    	}
    

    从容器缓存中获取Bean

    在上一步中我们已经获取到了真正的beanName,那么接下来,就可以利用这个beanName到容器的缓存中尝试获取bean,如果之前已经创建过,这里就可以直接获取到bean。这里的缓存包括三级,但是这三级缓存并不是包含的关系,而是一种互斥的关系,一个bean无论处于何种状态,它在同一时刻只能处于某个缓存当中。

    跟进getSingleton(beanName)方法代码。

    	public Object getSingleton(String beanName) {
    		return getSingleton(beanName, true);
    	}
    

    可以看到这里默认给多了一个参数为true,这参数为allowEarlyReference,用来控制是否允许循环依赖。方法代码注释比较详细,就是逐个缓存去获取,跟着看一下问题不大。第一次进来肯定是获取不到任何东西的,所以这里会返回null

    	/**
    	 * Return the (raw) singleton object registered under the given name.
    	 * <p>Checks already instantiated singletons and also allows for an early
    	 * reference to a currently created singleton (resolving a circular reference).
    	 *
    	 * 返回在给定名称下注册的(原始)单例对象。
    	 * <p>检查已经实例化的单例,并允许提前引用当前创建的单例(解决循环引用)。
    	 *
    	 * @param beanName the name of the bean to look for 要查找的 bean 的名称
    	 * @param allowEarlyReference whether early references should be created or not 是否应创建早期引用
    	 * @return the registered singleton object, or {@code null} if none found 注册的单例对象,如果没有找到则为 {@code null}
    	 */
    	@Nullable
    	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    		// 检测一级缓存中是否存在实例
    		Object singletonObject = this.singletonObjects.get(beanName);
    		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
    			// 如果为空,则锁定全局变量进行处理
    			synchronized (this.singletonObjects) {
    				// 从二级缓存 earlySingletonObjects 中获取
    				singletonObject = this.earlySingletonObjects.get(beanName);
    				// 二级缓存中没有,并且 allowEarlyReference = true 允许提前创建早期引用,则到三级缓存中获取
    				// 早期引用一般是用来指向需要经过代理的bean或者是需要延迟初始化的bean
    				if (singletonObject == null && allowEarlyReference) {
    					// 当某些方法需要提前初始化的时候,则会调用addSingletonFactory方法
    					// 将对应的objectFactory初始化策略存储在singletonFactories
    					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
    					if (singletonFactory != null) {
    						// 这里的实现是一个lambada表达式,具体的实现有很多种
    						// 调用预先设定的getObject方法,也就是调用之前加入的 getEarlyBeanReference()方法
    						// 此表达式是在 doCreateBean() 方法中调用 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)) 加入的
    						singletonObject = singletonFactory.getObject();
    						// 将bean加入二级缓存中
    						this.earlySingletonObjects.put(beanName, singletonObject);
    						// 同时从三级缓存中将bean移除,也就是移除一个ObjectFactory,对应为一个lambada表达式
    						this.singletonFactories.remove(beanName);
    					}
    				}
    			}
    		}
    		return singletonObject;
    	}
    

    缓存存在bean

    这里讲解的是截图的第三部分,代码是第260行到276行左右。

    		if (sharedInstance != null && args == null) {
    			// 省略部分日志...
    			// 如果直接从单例池中获取到了这个 bean(sharedInstance),我们能直接返回吗?
    			// 当然不能,因为获取到的 Bean 可能是一个 factoryBean,
    			// 如果我们传入的 name 是 & + beanName 这种形式的话,
    			// 那是可以返回的,但是我们传入的更可能是一个 beanName,
    			// 那么这个时候 Spring 就还需要调用这个 sharedInstance 的 getObject 方法来创建真正被需要的 Bean
    			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    		}
    

    可以看到,去除日志后,只剩下一个主要的方法,跟进getObjectForBeanInstance()代码查看。可以看到这里会进行一些类型的判断,会尝试从缓存获取,最后会调用getObjectFromFactoryBean方法从FactoryBean里获取实例对象。

    	/**
    	 * Get the object for the given bean instance, either the bean
    	 * instance itself or its created object in case of a FactoryBean.
    	 *
    	 * 获取给定 bean 实例的对象,bean 实例本身或其创建的对象(如果是 FactoryBean)。
    	 *
    	 * @param beanInstance the shared bean instance
    	 * @param name name that may include factory dereference prefix
    	 * @param beanName the canonical bean name
    	 * @param mbd the merged bean definition
    	 * @return the object to expose for the bean
    	 */
    	protected Object getObjectForBeanInstance(
    			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
    
    		// Don't let calling code try to dereference the factory if the bean isn't a factory.
    		// 如果指定的name是工厂相关(以&为前缀)且 beanInstance又不是FactoryBean类型则验证不通过
    		if (BeanFactoryUtils.isFactoryDereference(name)) {
    			if (beanInstance instanceof NullBean) {
    				return beanInstance;
    			}
    			if (!(beanInstance instanceof FactoryBean)) {
    				throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
    			}
    			if (mbd != null) {
    				mbd.isFactoryBean = true;
    			}
    			return beanInstance;
    		}
    
    		// Now we have the bean instance, which may be a normal bean or a FactoryBean.
    		// If it's a FactoryBean, we use it to create a bean instance, unless the
    		// caller actually wants a reference to the factory.
    
    		// 现在我们有了 bean 实例,它可能是普通的 bean 或 FactoryBean。
    		// 如果它是一个 FactoryBean,我们使用它来创建一个 bean 实例,除非调用者实际上想要一个对工厂的引用。
    		// 如果是普通bean,直接返回了
    		if (!(beanInstance instanceof FactoryBean)) {
    			return beanInstance;
    		}
    
    		//加载factoryBean
    		Object object = null;
    		if (mbd != null) {
    			mbd.isFactoryBean = true;
    		}
    		else {
    			//尝试从缓存中获取
    			object = getCachedObjectForFactoryBean(beanName);
    		}
    		if (object == null) {
    			// Return bean instance from factory.
    			// 到这里可以确定 beanInstance 一定是 FactoryBean 类型
    			FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
    			// Caches object obtained from FactoryBean if it is a singleton.
    			// 如果是单例,则缓存从 FactoryBean 获得的对象。
    			// containsBeanDefinition 检测 beanDefinitionMap 中也就是在所有已经加载的类中检测是否定义 beanName
    			if (mbd == null && containsBeanDefinition(beanName)) {
    				// 将存储XML文件的 GenericBeanDefinition 转换为 RootBeanDefinition,如果指定的 beanName 是子 bean 的话
    				// 会同时合并父类的相关属性
    				mbd = getMergedLocalBeanDefinition(beanName);
    			}
    			//是否是用用户自己定义的还是用程序本身定义的
    			boolean synthetic = (mbd != null && mbd.isSynthetic());
    			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
    		}
    		return object;
    	}
    

    跟进getObjectFromFactoryBean()方法,该方法首先也是从缓存获取,然后调用doGetObjectFromFactoryBean()真正获取bean对象,这里会区分单例和原型分别去获取,单例获取完成后会放入缓存,原型则每次都新建,所以原型bean的创建前前后后会省略很多步骤。获取完成后根据shouldPostProcess判断是否需要后置处理,从而执行BeanPostProcessor#postProcessAfterInitialization()后置处理器的方法,最后将对象放入缓存中。这些处理思路跟我们平时写业务代码的思路也是非常类似的,可以互相借鉴一下。

    	/**
    	 * Obtain an object to expose from the given FactoryBean.
    	 *
    	 * 从给定的 FactoryBean 中获取要公开的对象。
    	 *
    	 * @param factory the FactoryBean instance
    	 * @param beanName the name of the bean
    	 * @param shouldPostProcess whether the bean is subject to post-processing bean是否经过后处理
    	 * @return the object obtained from the FactoryBean
    	 * @throws BeanCreationException if FactoryBean object creation failed
    	 * @see org.springframework.beans.factory.FactoryBean#getObject()
    	 */
    	protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
    		//如果是单例的话
    		if (factory.isSingleton() && containsSingleton(beanName)) {
    			//加锁,保证单例
    			synchronized (getSingletonMutex()) {
    				//先从缓存中获取
    				Object object = this.factoryBeanObjectCache.get(beanName);
    				if (object == null) {
    					//从FactoryBean中获取bean
    					object = doGetObjectFromFactoryBean(factory, beanName);
    					// Only post-process and store if not put there already during getObject() call above
    					// (e.g. because of circular reference processing triggered by custom getBean calls)
    					// 如果在上面的 getObject() 调用期间尚未放置,则仅进行后处理和存储(例如,由于自定义 getBean 调用触发的循环引用处理)
    					Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
    					if (alreadyThere != null) {
    						object = alreadyThere;
    					}
    					else {
    						if (shouldPostProcess) {
    							if (isSingletonCurrentlyInCreation(beanName)) {
    								// Temporarily return non-post-processed object, not storing it yet..
    								// 暂时返回非后处理对象,暂不存储..
    								return object;
    							}
    							beforeSingletonCreation(beanName);
    							try {
    								//调用ObjectFactory的后置处理器
    								object = postProcessObjectFromFactoryBean(object, beanName);
    							}
    							catch (Throwable ex) {
    								throw new BeanCreationException(beanName,
    										"Post-processing of FactoryBean's singleton object failed", ex);
    							}
    							finally {
    								afterSingletonCreation(beanName);
    							}
    						}
    						if (containsSingleton(beanName)) {
    							this.factoryBeanObjectCache.put(beanName, object);
    						}
    					}
    				}
    				return object;
    			}
    		}
    		else {
    			// 从 FactoryBean 获取对象
    			Object object = doGetObjectFromFactoryBean(factory, beanName);
    			if (shouldPostProcess) {
    				try {
    					// 后置处理从 FactoryBean 获取的对象
    					object = postProcessObjectFromFactoryBean(object, beanName);
    				}
    				catch (Throwable ex) {
    					throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
    				}
    			}
    			return object;
    		}
    	}
    

    跟进doGetObjectFromFactoryBean()方法,这个方法就更简单了,就是调用工厂bean的getObject()方法返回bean。

    	/**
    	 * Obtain an object to expose from the given FactoryBean.
    	 *
    	 * 从给定的 FactoryBean 中获取要公开的对象。
    	 *
    	 * @param factory the FactoryBean instance
    	 * @param beanName the name of the bean
    	 * @return the object obtained from the FactoryBean
    	 * @throws BeanCreationException if FactoryBean object creation failed
    	 * @see org.springframework.beans.factory.FactoryBean#getObject()
    	 */
    	private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
    			throws BeanCreationException {
    
    		Object object;
    		try {
    			//需要权限校验
    			if (System.getSecurityManager() != null) {
    				// 省略部分代码...
    			}
    			else {
    				//直接调用factory.getObject()方法
    				object = factory.getObject();
    			}
    		}
    		catch (Throwable ex) {
    			// 省略部分异常处理...
    		}
    
    		// Do not accept a null value for a FactoryBean that's not fully
    		// initialized yet: Many FactoryBeans just return null then.
    		// 不要为尚未完全初始化的 FactoryBean 接受 null 值:许多 FactoryBean 只返回 null。
    		if (object == null) {
    			if (isSingletonCurrentlyInCreation(beanName)) {
    				throw new BeanCurrentlyInCreationException(
    						beanName, "FactoryBean which is currently in creation returned null from getObject");
    			}
    			object = new NullBean();
    		}
    		return object;
    	}
    

    到这里,图片上的第三部分过完了。接下来是第四步。

    真正进入创建Bean的流程

    经过前面这么多铺垫,才真正走到了创建Bean的地方。这里会比较复杂且啰嗦,需要点耐心看完。

    这部分代码如下,可以跟着注释看下这段代码。这里先对原型类型的循环依赖进行校验,原型bean出现循环依赖直接抛异常。然后回去父容器里获取,紧接着又处理了被@DependsOn注解标注的依赖,然后再进行bean的创建。

    			// Fail if we're already creating this bean instance:
    			// We're assumably within a circular reference.
    			// 在缓存中获取不到这个Bean
    			// 原型下的循环依赖直接报错
    			if (isPrototypeCurrentlyInCreation(beanName)) {
    				throw new BeanCurrentlyInCreationException(beanName);
    			}
    
    			// Check if bean definition exists in this factory.
    			// 核心要义,找不到我们就从父容器中再找一次
    			// 我们简单的示例是不会有父容器存在的,这一块可以理解为递归到父容器中查找,跟在当前容器查找逻辑是类似的
    			BeanFactory parentBeanFactory = getParentBeanFactory();
    			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
    				// Not found -> check parent.
    				// 从父容器获取,根据不同的参数调用不同的方法
    				String nameToLookup = originalBeanName(name);
    				if (parentBeanFactory instanceof AbstractBeanFactory) {
    					return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
    							nameToLookup, requiredType, args, typeCheckOnly);
    				}
    				else if (args != null) {
    					// Delegation to parent with explicit args.
    					return (T) parentBeanFactory.getBean(nameToLookup, args);
    				}
    				else if (requiredType != null) {
    					// No args -> delegate to standard getBean method.
    					return parentBeanFactory.getBean(nameToLookup, requiredType);
    				}
    				else {
    					return (T) parentBeanFactory.getBean(nameToLookup);
    				}
    			}
    
    			// 如果不仅仅是为了类型推断,也就是代表我们要对进行实例化
    			// 那么就将bean标记为正在创建中,其实就是将这个beanName放入到alreadyCreated这个set集合中
    			if (!typeCheckOnly) {
    				markBeanAsCreated(beanName);
    			}
    
    			try {
    				// 为什么这里需要再获取一次,因为经过之前的操作,RootBeanDefinition 可能已经发生了改变,
    				// 其中的 stale 属性可能已经设为 true,这时需要去容器里重新获取,而不是直接从缓存中返回
    				// 例如上面的 markBeanAsCreated() 方法就会修改 stale 属性
    				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
    				// 检查合并后的bd是否是abstract,这个检查现在已经没有作用了,必定会通过
    				checkMergedBeanDefinition(mbd, beanName, args);
    
    				// Guarantee initialization of beans that the current bean depends on.
    				// @DependsOn注解标注的当前这个Bean所依赖的bean名称的集合,
    				// 就是说在创建当前这个Bean前,必须要先将其依赖的Bean先完成创建
    				String[] dependsOn = mbd.getDependsOn();
    				if (dependsOn != null) {
    					// 遍历所有申明的依赖
    					for (String dep : dependsOn) {
    						// 如果这个bean所依赖的bean又依赖了当前这个bean,出现了循环依赖,直接报错
    						if (isDependent(beanName, dep)) {
    							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    									"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
    						}
    						// 注册bean跟其依赖的依赖关系,key为依赖,value为依赖所从属的bean
    						registerDependentBean(dep, beanName);
    						try {
    							// 先创建其依赖的Bean
    							getBean(dep);
    						}
    						catch (NoSuchBeanDefinitionException ex) {
    							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    									"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
    						}
    					}
    				}
    
    				// Create bean instance.创建bean实例
    				// 我们目前只分析单例的创建,单例看懂了,原型自然就懂了
    				if (mbd.isSingleton()) {
    					// 这里再次调用了 getSingleton() 方法,
    					// 这里跟方法开头调用的 getSingleton() 的区别在于,
    					// 这个方法多传入了一个 ObjectFactory 类型的参数,
    					// 这个 ObjectFactory 会返回一个 Bean
    					sharedInstance = getSingleton(beanName, () -> {
    						try {
    							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.
    							// 从单例缓存中显式删除实例:它可能已被创建过程提前地放在那里,以允许循环引用解析。
    							// 还要删除任何接收到对 bean 的临时引用的 bean。
    							destroySingleton(beanName);
    							throw ex;
    						}
    					});
    					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    				}
    
    				else if (mbd.isPrototype()) {
    					// It's a prototype -> create a new instance.
    					Object prototypeInstance = null;
    					try {
    						beforePrototypeCreation(beanName);
    						prototypeInstance = createBean(beanName, mbd, args);
    					}
    					finally {
    						afterPrototypeCreation(beanName);
    					}
    					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
    				}
    
    				else {
    					String scopeName = mbd.getScope();
    					final Scope scope = this.scopes.get(scopeName);
    					if (scope == null) {
    						throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
    					}
    					try {
    						Object scopedInstance = scope.get(beanName, () -> {
    							beforePrototypeCreation(beanName);
    							try {
    								return createBean(beanName, mbd, args);
    							}
    							finally {
    								afterPrototypeCreation(beanName);
    							}
    						});
    						bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
    					}
    					catch (IllegalStateException ex) {
    						// 省略部分异常处理...
    					}
    				}
    			}
    			catch (BeansException ex) {
    				cleanupAfterBeanCreationFailure(beanName);
    				throw ex;
    			}
    

    其实去掉部分校验,去掉部分复杂场景下才会有的逻辑,核心代码就是getSingleton(String beanName, ObjectFactory<?> singletonFactory) 方法,这个方法是不是有点眼熟,getSingleton()有三个同名的重载方法。前两个上面已经见过,这里是第三个。

    1653556824388

    仔细看这段代码,singletonFactory部分传入的是个lambada表达式,里面是正常创建bean的createBean()方法。

    sharedInstance = getSingleton(beanName, () -> {
    						try {
    							return createBean(beanName, mbd, args);
    						}
    						catch (BeansException ex) {
    							// 省略部分异常处理...
    						}
    					});
    

    结合getSingleton()方法查看,该方法处理一些前置判断和后置处理后,核心的代码就是singletonFactory.getObject()方法,这里执行的就是上面传入的lambada表达式,也就是会执行到createBean(beanName, mbd, args)方法。createBean(beanName, mbd, args)又是一个很曲折的方法,简直是曲折他妈给曲折开门,曲折到家了。所以我打算下一篇Spring Ioc源码分析系列--Bean实例化过程(二)说。在创建完成后,会把bean放入单例缓存singletonObjects中。

    	/**
    	 * Return the (raw) singleton object registered under the given name,
    	 * creating and registering a new one if none registered yet.
    	 *
    	 * 返回以给定名称注册的(原始)单例对象,如果尚未注册,则创建并注册一个新对象。
    	 *
    	 * @param beanName the name of the bean
    	 * @param singletonFactory the ObjectFactory to lazily create the singleton
    	 * with, if necessary
    	 * @return the registered singleton object
    	 */
    	public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    		Assert.notNull(beanName, "Bean name must not be null");
    		synchronized (this.singletonObjects) {
    			// 从单例池中获取,第一次进来这个地方肯定获取不到
    			Object singletonObject = this.singletonObjects.get(beanName);
    			if (singletonObject == null) {
    				// 工厂已经在销毁阶段了,这个时候还在创建Bean的话,就直接抛出异常
    				if (this.singletonsCurrentlyInDestruction) {
    					// 省略部分日志及异常处理...
    				}
    				// 在单例创建前,记录一下正在创建的单例的名称,
    				// 就是把beanName放入到singletonsCurrentlyInCreation这个set集合中去
    				beforeSingletonCreation(beanName);
    				boolean newSingleton = false;
    				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
    				if (recordSuppressedExceptions) {
    					this.suppressedExceptions = new LinkedHashSet<>();
    				}
    				try {
    					// 这里调用了singletonFactory的getObject方法,
    					// 对应的实现就是在doGetBean中的那一段lambda表达式
    					singletonObject = singletonFactory.getObject();
    					newSingleton = true;
    				}
    				catch (IllegalStateException ex) {
    					// Has the singleton object implicitly appeared in the meantime ->
    					// if yes, proceed with it since the exception indicates that state.
    					// 单例对象是否同时隐式出现 -> 如果是,则继续执行,因为异常指示该状态。
    					singletonObject = this.singletonObjects.get(beanName);
    					if (singletonObject == null) {
    						throw ex;
    					}
    				}
    				catch (BeanCreationException ex) {
    					// 省略部分异常处理...
    				}
    				finally {
    					if (recordSuppressedExceptions) {
    						this.suppressedExceptions = null;
    					}
    					// 在单例完成创建后,将beanName从singletonsCurrentlyInCreation中移除
    					// 标志着这个单例已经完成了创建
    					afterSingletonCreation(beanName);
    				}
    				if (newSingleton) {
    					// 添加到单例池中
    					addSingleton(beanName, singletonObject);
    				}
    			}
    			return singletonObject;
    		}
    	}
    

    进行类型转换

    这里已经分析到了截图的第五部分,由于第四部分真正创建bean的部分放到了下一篇Spring Ioc源码分析系列--Bean实例化过程(二)去分析,所以到这里的时候,我们已经完成了bean的创建,这个时候,如果方法传入的requiredType不为空,那么就需要进行类型转换,如果转换失败,则抛出异常。转换成功则返回当前完成类型转换的convertedBean。至此,创建bean的流程结束,已经可以返回一个可使用的bean,是不是还是挺简单的。流程清晰。关于Spring的类型转换和校验也可以分一篇文章去分析TypeConverterConversionService在Spring体系里的前世今生,这里就不再赘述了。

    		// Check if required type matches the type of the actual bean instance.
    		// 检查所需类型是否与实际 bean 实例的类型匹配。
    		if (requiredType != null && !requiredType.isInstance(bean)) {
    			try {
    				T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
    				if (convertedBean == null) {
    					throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
    				}
    				return convertedBean;
    			}
    			catch (TypeMismatchException ex) {
    				if (logger.isTraceEnabled()) {
    					logger.trace("Failed to convert bean '" + name + "' to required type '" +
    							ClassUtils.getQualifiedName(requiredType) + "'", ex);
    				}
    				throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
    			}
    		}
    

    回调SmartInitializingSingleton实现类

    到这里完成单例bean的创建了,那就到了最后一步了,回调SmartInitializingSingleton#afterSingletonsInstantiated()方法,这里没啥好说的,就是第二个循环干的事。遍历所有的beanNames,然后完成回调。

    这里的回调有很多实现类,比较经典的是EventListenerMethodProcessor类,该类会在这一步完成了对已经创建好的Bean的解析,会判断其方法上是否有 @EventListener注解,会将这个注解标注的方法通过EventListenerFactory转换成一个事件监听器并添加到监听器的集合中。

    总结

    这篇文章还是按照之前的行文思路,分析得比较扁平,每个方法都没有特别过分的深入去讲解,因为那样太深了很多人受不了,容易翻车。

    回顾一下本文的思路,先是顺着上文的入口,开始分析bean的创建。首先是获取BeanDefinition,然后是调用getBean(beanName)方法进行对象的实例化。该方法由一个截图,分为了五部分去解析。分为了哪五部分还记得吗?忘记了?那不怪你,我瞎几把写的。

    第四步创建bean的部分我留到了下一篇去分析,这样思路应该也比较清晰,不会那么容易翻车。

    如果有人看到这里,那在这里老话重提。与君共勉,路漫漫其修远兮,吾将上下而求索。


    __EOF__

  • 本文作者: 幻想症患者
  • 本文链接: https://www.cnblogs.com/codegitz/p/16314523.html
  • 关于博主: 评论和私信会在第一时间回复。或者直接私信我。
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  • 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。
  • 相关阅读:
    量子多体理论怎么样理解,多体系统的量子理论
    Python异常处理 Python文件操作
    传统用户管理方案有哪些利弊?
    地平线 自动化测试|测试开发 面试真题|面经 汇总
    Echarts数据分析系统Data Analysis Platform使用说明文档
    Vue3 + TypeScript
    Unity学习笔记[一] RollBall小游戏
    【C++基于多设计模式下的同步&异步日志系统】
    如何在 Buildroot 中配置 Samba
    【10套模拟】【6】
  • 原文地址:https://www.cnblogs.com/codegitz/p/16314523.html