Java教程

Spring源码解析3.加载Bean上

本文主要是介绍Spring源码解析3.加载Bean上,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

参考

>>>doGetBean()方法解析

	protected <T> T doGetBean(
			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException {
		
        /*
         * 第一环节: 处理携带 &的name。这里最终获取的就是beanName
         */
		String beanName = transformedBeanName(name);
		Object bean;

		/*
		 * 第二环节:从缓存中尝试获取对象
		 */
		Object sharedInstance = getSingleton(beanName);
        
       	
        /*
 		 * 第三环节: 3.1从缓存中获取的对象不为NULL。       
         */
		if (sharedInstance != null && args == null) {
		   /*
			*  这里为什么又要套呢?为什么不直接缓存呢?
			*  因为从缓存中拿到的对象,可能是普通单实例,也可能是FactoryBean实例,
			*  如果是FactoryBean实例,这个时候还要进行处理,主要是看name是否携带 '&'
			*  (携带&说明想要获取FactoryBean实例(很少用),不携带&说明想要获取内部创建的			    *  复杂对象实例(常用))
			*
			*  这里最终返回要么是FactoryBean对象要么是getObject()创建的对象。
			*  (这里如果是获取的内部创建的复杂对象并且是单例的,会将其放到缓存中)
			* */
	    bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}
		
        
        /*
         * 以下环节的前提:从缓存中获取的对象为NULL。
         */
		else {
			
            /*
			*  原型模式循环依赖的判定(Spring无法处理,只能抛出异常)
			*   (即原型模式对象A依赖一个B(B可能是原型也可能不是原型),B依赖A)
			*     1.当前线程会在ThreadLoal中的Set集合中存储一个字符串"A",表示当前正在			 *   	 创建A对象
			*     2.此时创建出来的A对象是一个早期对象
			*     3.处理A的依赖,发现A依赖了B类型的对象,触发了getBean(B)的逻辑
			*     4.根据B构造方法创建出B的早期实例
			*     5.处理B的依赖,发现依赖了A
			*     6.然后继续走上getBean("A")的逻辑,但是此时ThreadLocal的set集合中存			 *		 在A字符串说明当前A正在创建中,表示发生了循环依赖,此时直接抛出异常。 
			* */
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			//这里处理父子容器(不再详细分析)
			BeanFactory parentBeanFactory = getParentBeanFactory();
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				
				String nameToLookup = originalBeanName(name);
				if (parentBeanFactory instanceof AbstractBeanFactory) {
					return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
							nameToLookup, requiredType, args, typeCheckOnly);
				}
				else if (args != null) {
					
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else if (requiredType != null) {
					
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
				else {
					return (T) parentBeanFactory.getBean(nameToLookup);
				}
			}

			if (!typeCheckOnly) {
				markBeanAsCreated(beanName);
			}

			try {
                //第五环节 - 合并bd 返回合并后的mbd。
				RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                
                //判断当前bd是否为抽象bd,抽象bd直接抛出异常。
				checkMergedBeanDefinition(mbd, beanName, args);

			   /*
				*  第六环节-处理depends-on依赖
				*   <bean id = "A" depends-on = "B" >
				*   <bean id = "B">
				*
				*   循环依赖问题
				*   <bean id = "A" depends-on = "B" >
				*   <bean id = "B" depends-on = "A">
				*   Spring是处理不了这种情况的,需要报错。。
				*   Spring需要发现这种情况的产生。
				*   如何发现? 依靠两个Map
				*     1.dependentBeanMap 记录依赖当前beanName的其他beanName
				*     2.dependenciesForBeanMap 记录当前beanName依赖的其他beanName				*		集合。
				* */
                //获取A的depends-on的所有对象
				String[] dependsOn = mbd.getDependsOn();
                //不为NULL。
				if (dependsOn != null) {
                    //遍历所有的depends-on对象
					for (String dep : dependsOn) {
                        //判断循环依赖
						if (isDependent(beanName, dep)) {
							//这里抛出异常了 由于代码太长这里省略
						}
                        //将依赖关系注册到两个Map中
						registerDependentBean(dep, beanName);
						try {
                            //先去获取依赖的对象。
							getBean(dep);
						}
						catch (NoSuchBeanDefinitionException ex) {
							//抛出异常
					}
				}

				// 第七环节mbd是单例,创建出单例对象
				if (mbd.isSingleton()) {
                    //从缓存中获取
					sharedInstance = getSingleton(beanName, () -> {
						try {
                            /*
                             * 创建根据beanName和bd创建出实例对象,创建后会放入缓存
                             *  createBean()核心方法,
                             */
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							destroySingleton(beanName);
							throw ex;
						}
					});
                    
                    //这里的逻辑跟3.1.1一样,还要判断&的情况
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}

				else if (mbd.isPrototype()) {
					Object prototypeInstance = null;
					try {
                        /*
                         * 这里会将当前的beanName放到ThreadLoacl的Set集合中去,
                         * 表示当前的这个beanName表示的对象正在创建中。
                         * 后续如果当前bd与某个bd产生了循环依赖,走到第四环节Spring就						  *	会发现产生了原型循环依赖(Spring无法处理),直接抛出异常。
                         * 
                         */
						beforePrototypeCreation(beanName);
                        //创建对象
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
                        //创建完毕 会将Set中的当前beanName干掉。
						afterPrototypeCreation(beanName);
					}
					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}
				
                //scope除了singleton和prototye其他情况很少见,这里就不在分析了
				else {
                    //....
                }
		}

		//类型
		if (requiredType != null && !requiredType.isInstance(bean)) {
			try {
				//检查需要的类型是够符合Bean的实际类型
                T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
				if (convertedBean == null) {
					//抛出异常
				}
                //需要转换则进行一次转换。
				return convertedBean;
			}
			catch (TypeMismatchException ex) {
				if (logger.isTraceEnabled()) {
					//打印日志
				}
				//抛出异常
			}
		}
        //返回bean。
		return (T) bean;
	}

第一环节-处理beanName

1.1transformedBeanName()

public static String transformedBeanName(String name) {
		Assert.notNull(name, "'name' must not be null");
		
		/*
		*  FACTORY_BEAN_PREFIX = '&'
		*  name不是以&开头的,直接return即可
		* */
		if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
			return name;
		}
		
		/*
		*  transformedBeanNameCache是一个Map,computeIfAbsent()方法
		*  当key = NULL 或者 value = NULL时,这次put操作就会成功(并且会返回value),否则就会失败
		*  最终Map中存一个(&person, person)
		* */
		return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
			do {
				/*
				*  截取一下,将&干掉。 例如 "&person" -> "person"
				* */
				beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
			}
			while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
			//最终将去掉&的name返回
			return beanName;
		});
	}

1.2canonicalName()

	/*
	*  从alilasMap中查找
	*  ["C" : "B"] ["B" : "A"] 即 A有一个别名是 B,B有一个别名是C, 
	*  这里就是在循环查找 C -> B -> A的过程。 因为在map中是没有A作为Key的Entry的。  
	* */
	public String canonicalName(String name) {
		String canonicalName = name;
		String resolvedName;
		do {
			resolvedName = this.aliasMap.get(canonicalName);
			if (resolvedName != null) {
				canonicalName = resolvedName;
			}
		}
		while (resolvedName != null);
		//最终返回A
		return canonicalName;
	}

第二环节-尝试从缓存中获取实例

2.1关于三级缓存

	/*
	*  一级缓存,key -> beanName : value创建出的单实例对象(经过完整生命周期)
	* */
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

	/*
	*  三级缓存,当一个单实例bean刚被创建出来时(还未完成初始化等后续操作),会将当前bean实例
	*          包装成一个ObjectFactory对象放到三级缓存。
	* */
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

	/*
	* 二级缓存 : 用来保存实例化完成,但是还未初始化完成的对象
	* key -> beanName : value -> Bean实例 
	* 当单实例bean正在创建过程中时,会先放到三级缓存中,然后其他线程调用getBean()时,
	* 从三级缓存中获取到了bean对象,然后就会将此bean从三级缓存中干掉,放到二级缓存中去
	* 
	* */
	private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);

2.2关于ObjectFactory

Spring为单实例对象创建的早期对象会被封装为一个ObjectFactory的实现类,调用内部的getObject()方法可以得到内部的早期对象(也可能是早期对象的代理类对象(AOP)),然后会被放到三级缓存的**singletonFactories(Map)**中。

@FunctionalInterface
public interface ObjectFactory<T> {

	T getObject() throws BeansException;
}

2.3getSingleton()

   /*
	*  @param allowEarlyReference 是否允许早期引用 
	* 最终返回值情况
	*  1.一级缓存中找到,返回
	*  2.一级缓存没找到,二级缓存中找到 返回
	*  3.一二级缓存都没有,三级缓存(ObjectFactory)中找到,将三级缓存中的对象干掉放到二级	*  缓存,并返回 
	*/
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {

		//从一级缓存中拿
		Object singletonObject = this.singletonObjects.get(beanName);
		/*
		*  满足下面的if条件:(一级缓存没有 并且 当前的bean对象正在创建中)
		*  Spring会将正在创建的bean的beanName加入到一个Set集合中。
		*
		*  条件一成立(singletionObject == null) 有几种可能?
		*  1.单实例确实未创建
		*  2.单实例正在创建中,当前发生了循环依赖
		*
		*  什么是循环依赖?  A依赖B,B依赖A。
 		*  单实例有几种循环依赖呢?
		*  1.构造方法循环依赖 (无解)
		*  2.set注入循环依赖  (有解,依靠三级缓存解决)
		*
		*  三级缓存如何解决set注入造成的循环依赖。
		*   举个例子 A -> B , B - A.
		*   1.假设Spring先实例化A,首先拿到A的构造方法,然后反射创建出A的早期对象,这时,		*     这个早期对象被包装成了ObjectFactory对象放到了三级缓存中
		*	2.处理A的依赖数据,检查发现A依赖了B,所以接下来就走到getBean(B)的逻辑
		*   3.拿到B的构造方法然后反射创建早期实例对象,也会将B包装成ObjectFactory放到三		  *		级缓存中
		*   4.处理B的依赖数据,发现B依赖了A,所以接下来就会又走到getBean(A)去获得A对象,
		*   5.所以程序这时会走到当前这个getSingleton()方法
		*   6.走到这里的if判断,两个判断都会成立(1.A不在一级缓存中 2.A正在创建)
		* */
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			//从二级缓存中获取
			singletonObject = this.earlySingletonObjects.get(beanName);
			//二级缓存也没有 去三级缓存中查看。
			if (singletonObject == null && allowEarlyReference) {
				//加锁
				synchronized (this.singletonObjects) {

					/*
					*  Spring为什么需要有三级缓存存在,而不是只有二级缓存呢?
					*  AOP,靠动态代理实现。
					*  3级缓存在这里又什么目的呢?
					*  三级缓存中保存的是ObjectFactory,里面保存着原生的对象引用,						*  getObject()方法需要考虑的是要返回
					*  原生对象还是增强后的对象,getObject()方法会判断当前这个早期实例					*  是否需要被增强,如果需要的话,那么必须提前完成动态代理增强
					*  返回代理对象,否则返回原生对象。
					* */
                     
					//尝试继续从一级缓存中获取
					singletonObject = this.singletonObjects.get(beanName);
					//一级缓存中不存在
					if (singletonObject == null) {
						//再次尝试从二级缓存中获取
						singletonObject = this.earlySingletonObjects.get(beanName);
						//二级缓存也不存在
						if (singletonObject == null) {
							//从三级缓存中获取
							ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
							//三级缓存不为NULL
							if (singletonFactory != null) {
								//获取包装的ObjectFactory中的早期对象
								singletonObject = singletonFactory.getObject();
								//将早期对象放到二级缓存中
								this.earlySingletonObjects.put(beanName, singletonObject);
								//将这个beanName对应的ObjectFactory从三级缓存中干掉
								this.singletonFactories.remove(beanName);
							}
						}
					}
				}
			}
		}
		return singletonObject;
	}

第三环节-判断从缓存中获取对象的情况

3.1从缓存中获取对象不为NULL

3.1.1getObjectForBeanInstance()

		/*
		 * 此方法就是判断getBean时的name情况是否是普通单实例或者是FactoryBean实例
		 * 传入从缓存中获取实例(不为NULL)。
		 *
		 * 1.name携带了&,说明想要获取的就是FactoryBean的实现类对象,直接返回。
		 * 2.name没有携带&
		 *  2.1获取的缓存对象不属于FactoryBean类型,说明是普通单实例对象,直接返回
		 *  2.2获取的缓存对象属于FactoryBean类型,且name没有携带&,说明此时想要获取的就
		 *     是FactoryBean.getObject()创建的对象。
		 *     此时需要先判断是否可以从(beanName -> FactoryBean内部对象)的map中获取
		 *     获取成功返回,获取失败调用内部的getObject()方法拿到内部对象,然后返回
		 *     (注意:如果FactoryBean内部的对象规定为单例的,那么拿到内部的对象后还需要放		   *     到缓存中,否则不需要放入缓存)
		 */
		protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

		// 判断name是否携带了& 条件成立,说明要获取的是FactoryBean实例
		if (BeanFactoryUtils.isFactoryDereference(name)) {
			if (beanInstance instanceof NullBean) {
				return beanInstance;
			}
			//从缓存中获取的实例不是FactoryBean实例,说明获取错误,抛出异常
			if (!(beanInstance instanceof FactoryBean)) {
				//抛出异常
			}
			//给当前的bean实例对应的mbd打一个标记,表明当前实例是一个FactoryBean
			if (mbd != null) {
				mbd.isFactoryBean = true;
			}
			//还是返回缓存中的实例
			return beanInstance;
		}

		/*
		 *  执行到这里,有几种情况?
		 * 1.当前bean实例就是普通单实例
		 * 2.当前bean实例是FactoryBean接口实现类,且想要获取内部创建的复杂对象实例
		 * */

		//1.当前bean实例就是普通单实例
		if (!(beanInstance instanceof FactoryBean)) {
			return beanInstance;
		}

		/*
		* 2.当前bean实例是FactoryBean接口实现类,且想要获取内部创建的复杂对象实例
		*/

		//object保存FactoryBean实现类内部创建的对象
		Object object = null;
		if (mbd != null) {
			mbd.isFactoryBean = true;
		} else {
			//尝试从缓存中获取FactoryBean.getObject()的返回值对象
			object = getCachedObjectForFactoryBean(beanName);
		}
		//缓存中获取不到
		if (object == null) {
			//将beanInstance强转为FactoryBean对象
			FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
			/*
			*  条件一: 一般都成立
			*  条件二: 判断是否存在当前beanName对应的bd
			* */
			if (mbd == null && containsBeanDefinition(beanName)) {
				//合并bd
				mbd = getMergedLocalBeanDefinition(beanName);
			}
			// synthetic默认为false,表示这是一个用户对象,true表示是系统对象
			boolean synthetic = (mbd != null && mbd.isSynthetic());
			//获取FactoryBean内部getObject()创建的对象
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		//返回object
		return object;
	}

3.1.2getObjectFromFactoryBean()

		/*
		 * 判断FactoryBean内部的对象是单例还是原型模式,
		 *(加锁) 单例: 先从缓存中拿,拿不到调用getObject()获取对象,然后放到缓存中并返回
		 * 原型: 直接调用getObject()获取对象
		 */ 
		protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {

		/*
		*  CASE1 FactoryBean内部维护的对象是单实例
		* */
		if (factory.isSingleton() && containsSingleton(beanName)) {
			//加锁
			synchronized (getSingletonMutex()) {
				//尝试从缓存中获取 当前FactoryBean的beanName对应的内部实例
				Object object = this.factoryBeanObjectCache.get(beanName);
				//缓存中没有
				if (object == null) {
					//这里就是调用FactoryBean对象内部的getObject()方法获取内部对象
					object = doGetObjectFromFactoryBean(factory, beanName);
			
					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 {
								//执行后处理器
								object = postProcessObjectFromFactoryBean(object, beanName);
							}
							catch (Throwable ex) {
								//抛异常
							}
							finally {
								afterSingletonCreation(beanName);
							}
						}
						if (containsSingleton(beanName)) {
							//将beanName -> 内部的Object(单实例) 放到缓存中(Map)中
							this.factoryBeanObjectCache.put(beanName, object);
						}
					}
				}
				//最终返回内部的object
				return object;
			}
		}
		/*
		*  FactoryBean内部维护的对象非单实例
		* */
		else {
			//直接调用FactoryBean内部的getObject()方法获取对象
			Object object = doGetObjectFromFactoryBean(factory, beanName);
			if (shouldPostProcess) {
				try {
					//执行后处理器
					object = postProcessObjectFromFactoryBean(object, beanName);
				}
				catch (Throwable ex) {
					//抛出异常
				}
			}
			//返回object
			return object;
		}
	}

(以下环节都是从缓存中获取对象为NULL后的环节)

第四环节-判断原型模式循环依赖

	protected boolean isPrototypeCurrentlyInCreation(String beanName) {
		/*
		* prototypesCurrentlyInCreation(ThreadLocal)
		*  获取内部的set集合或者字符串,然后判断beanName是否存在。存在说明发生了循环依赖
		* */
		Object curVal = this.prototypesCurrentlyInCreation.get();
		return (curVal != null &&
				(curVal.equals(beanName) || (curVal instanceof Set && ((Set<?>) curVal).contains(beanName))));
	}

第五环节-合并BeanDefinition信息

	protected RootBeanDefinition getMergedBeanDefinition(
			String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
			throws BeanDefinitionStoreException {

		synchronized (this.mergedBeanDefinitions) {
			//表示合并后的bd信息
			RootBeanDefinition mbd = null;
			//表示当前beanName对应的过期mbd信息
			RootBeanDefinition previous = null;

			// Check with full lock now in order to enforce the same merged instance.
			if (containingBd == null) {
				mbd = this.mergedBeanDefinitions.get(beanName);
			}

			//条件成立:表示mbd是NULL 或者是过期的
			if (mbd == null || mbd.stale) {
				//赋值给previous
				previous = mbd;
				//当前bd没有父bd,就不需要处理继承了
				if (bd.getParentName() == null) {
					// 克隆一个bd赋值给mbd (当前bd就是RootBeanDefinition)
					if (bd instanceof RootBeanDefinition) {
						mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
					} else {
						//传入当前bd构造一个RootBeanDefinition
						mbd = new RootBeanDefinition(bd);
					}
					//当前bd使用了继承,需要进行合并
				} else {
					//父bd信息
					BeanDefinition pbd;
					try {
						//获取处理了别名和&的真实父bd 的beanName
						String parentBeanName = transformedBeanName(bd.getParentName());
						//条件成立:子bd和父bd名称不一样,就是普通情况
						if (!beanName.equals(parentBeanName)) {
							//这里是一个递归调用,最终返回父bd信息
							pbd = getMergedBeanDefinition(parentBeanName);
						//非一般情况,子bd和父bd名称一样
						} else {
							BeanFactory parent = getParentBeanFactory();
							if (parent instanceof ConfigurableBeanFactory) {
								pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
							} else {
								//抛出异常
							}
						}
					} catch (NoSuchBeanDefinitionException ex) {
						throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
								"Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
					}
					//按照父bd信息创建一个RootBD,赋值给mbd
					mbd = new RootBeanDefinition(pbd);
					//子bd覆盖mbd信息,以子bd为基准,pbd为辅
					mbd.overrideFrom(bd);
				}

				if (!StringUtils.hasLength(mbd.getScope())) {
					mbd.setScope(SCOPE_SINGLETON);
				}

				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)
				if (containingBd == null && isCacheBeanMetadata()) {
					//缓存mbd信息
					this.mergedBeanDefinitions.put(beanName, mbd);
				}
			}
			if (previous != null) {
				copyRelevantMergedBeanDefinitionCaches(previous, mbd);
			}
            //返回合并后的mbd。
			return mbd;
		}
	}

第六环节-处理depends-on属性

6.1registerDependentBean

	/*
	 *  注册依赖关系
	 *  <bean id = "A" depends-on = "B">
	 *  这里的dep 就是B, beanName就是A
	 *  所以这里 beanName = B, dependentBeanName = A
	 * */
	public void registerDependentBean(String beanName, String dependentBeanName) {
		//循环在alilasMap中查找最终的B的beanName
		String canonicalName = canonicalName(beanName);
		
		/*
		*  这里在 dependentBeanMap存储 B -> (A) <即B被A依赖>
		* */
		synchronized (this.dependentBeanMap) {
			Set<String> dependentBeans =
					this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
			if (!dependentBeans.add(dependentBeanName)) {
				return;
			}
		}
		
		/*
		* 这里在 dependenciesForBeanMap中存储 A -> (B) <即A依赖B>
		* */
		synchronized (this.dependenciesForBeanMap) {
			Set<String> dependenciesForBean =
					this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
			dependenciesForBean.add(canonicalName);
		}
	}

6.2sisDependent()

private boolean isDependent(String beanName, String dependentBeanName, @Nullable Set<String> alreadySeen) {
		if (alreadySeen != null && alreadySeen.contains(beanName)) {
			return false;
		}
		String canonicalName = canonicalName(beanName);
		Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
		if (dependentBeans == null) {
			return false;
		}
    	//这里如果有循环依赖的话(双标签),通过上面的两个Map会发现,这里就返回true。
		if (dependentBeans.contains(dependentBeanName)) {
			return true;
		}
    
		for (String transitiveDependency : dependentBeans) {
			if (alreadySeen == null) {
				alreadySeen = new HashSet<>();
			}
			alreadySeen.add(beanName);
			if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {
				return true;
			}
		}
		return false;
	}

第七环节-创建(单)实例流程

这里我们以创建单实例(即scope = singleton)为例子来讲解源码。

7.1getSingleton()

	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) {
              //容器销毁时,会设置这个属性为true,这个时候就不能在创建bean了,直接抛错
				if (this.singletonsCurrentlyInDestruction) {
					//...抛出异常
				}
                
                /*
                 * 将当前beanName放入到"正在创建中的单实例集合(Set)",放入成功,
                 * 表示没有产生循环依赖,失败则产生循环依赖,会抛出异常
                 *   举个例子:构造方法参数依赖 
                 *   A -> B  B -> A
                 *   1.加载A,根据A的构造方法,想要去实例化A对象,但是发现A的构造方法
                 *     有一个参数是B(在这之前,已经向集合中添加了A)
                 *   2.因为A的构造方法依赖B,所以触发加载B的逻辑
                 *   3.加载B,根据B的构造方法去实例化B,但是发现B的构造方法有一个参数是
                 *     A(在这之前,已经向这个集合中添加了(A, B))
                 *   4.因为B的构造方法依赖A,所以再次触发加载A的逻辑
                 *   5.再次来到这个getSingleton方法里,调用
                 *    beforeSingletonCreation(A),因为创建中集合已经有A了,所以添加失					*    败,抛出异常
                 */
				beforeSingletonCreation(beanName);
                
                //创建单实例是否成功的标志。
				boolean newSingleton = false;
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = new LinkedHashSet<>();
				}
				try {
                    /*
					 * 这里调用了singletonFactory.getObject()方法,因为传入的实现类
                     * 调用的是createBean()方法,所以这里会去创建对象。
                     * 一般情况这里都会创建成功
                     */
					singletonObject = singletonFactory.getObject();
                    //创建成功标志位置为true
					newSingleton = true;
				}
				catch (IllegalStateException ex) {
					singletonObject = this.singletonObjects.get(beanName);
					if (singletonObject == null) {
						throw ex;
					}
				}
				catch (BeanCreationException ex) {
					if (recordSuppressedExceptions) {
						for (Exception suppressedException : this.suppressedExceptions) {
							ex.addRelatedCause(suppressedException);
						}
					}
					throw ex;
				}
				finally {
					if (recordSuppressedExceptions) {
						this.suppressedExceptions = null;
					}
                    //从正在创建的集合中删除当前beanName。
					afterSingletonCreation(beanName);
				}
                //正常逻辑,createBean()会创建成功,
				if (newSingleton) {
                    //这里将二级三级缓存当前beanName的对象全部清空,然后加入一级缓存中
					addSingleton(beanName, singletonObject);
				}
			}
            //最终返回。
			return singletonObject;
		}
	}

7.2addSingletion()

	protected void addSingleton(String beanName, Object singletonObject) {
		synchronized (this.singletonObjects) {
            //将当前bean实例加入一级缓存
			this.singletonObjects.put(beanName, singletonObject);
            //将当前的bean实例从三级缓存干掉
			this.singletonFactories.remove(beanName);
            //将当前的beanName对应的实例从二级缓存干掉。
			this.earlySingletonObjects.remove(beanName);
            //加入已注册单实例集合(Set)中
			this.registeredSingletons.add(beanName);
		}
	}

7.3beforeSingletonCreation()

  protected void beforeSingletonCreation(String beanName) {
    
    	/*
    	 * 条件一一般都成立
    	 * 条件二:singletonsCurrentlyInCreation(Set集合),表示当前beanName的单实例		 * 对象正在创建中添加set失败,直接抛出异常。
    	 */
		if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
			throw new BeanCurrentlyInCreationException(beanName);
		}
	}

7.4createBean()

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

		RootBeanDefinition mbdToUse = mbd;

		//加载bd内部的class到JVM中,并返回Class对象
		Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
		
    	//这里保证bd内部的beanClass(Object)一定不为NULL。
		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
			//重新构造一个bd
			mbdToUse = new RootBeanDefinition(mbd);
			//将Class设置进去
			mbdToUse.setBeanClass(resolvedClass);
		}

		// 处理方法重写。。。
		try {
			mbdToUse.prepareMethodOverrides();
		}

		try {
			/*
			* 这里通过后处理器,在这一步返回一个代理实例对象,注意,这里的代理对象不是AOP逻			  *	辑实现的地方。
			* 这里也并非是BeanPostPressor的执行过程(BPP是在Bean对象已经被创建出来后执			 * 行的,这里Bean还没有被创建)
			* */
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			//如果通过代理创建出来了对象,这里直接返回了。
			if (bean != null) {
				return bean;
			}
		}
		try {
			/*
			*  核心方法doCreateBean(), 创建bean实例,进行依赖注入,执行生命周期方法
			*  等都是在这个方法中完成的,下期我们将主要讲解此方法。
			* */
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
			if (logger.isTraceEnabled()) {
				//打印日志
			}
            //最终返回
			return beanInstance;
		}
	}

7.5总结第七环节创建单实例Bean的流程

  • 对象的创建是在createBean()方法完成的。
  • 进入getSingleton()中,会先尝试将当前要创建对象的beanName放到一个Set集合中(表示当前beanName对应的对象正在处于正在创建状态),放入失败说明发生了循环依赖(走到这里说明一二三缓存中都没有当前beanName对应的对象 (参考第二环节) ),直接抛出异常。
  • 然后调用createBean()方法开始创建对象,在寻找到合适的构造器后,然后反射创建对象(还未执行后续的生命周期方法),然后就会将这个早期对象包装成一个ObjectFactory放到三级缓存中(这里后续如果在创建其他对象的过程中调用了getBean(当前对象)的逻辑,那么就会从三级缓存中拿到当前的早期对象,然后将三级缓存中的当前对象删除并放到二级缓存中去。)
  • 后续执行属性注入、init-method等生命周期方法对这个对象进行完整的初始化。
  • createBean()方法执行成功后(一个完整的对象诞生)会将当前的beanName从(正在创建的对象)Set集合中干掉,然后将当前对象(已经执行了完整生命周期)放到一级缓存中,然后将二级三级缓存中的当前beanName的对象全部干掉
  • 判断创建的bean是否需要进行类型转换,最终返回创建的对象。
这篇关于Spring源码解析3.加载Bean上的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!