【spring 源碼】IOC 之 bean實例初始化

【spring 源碼】IOC 之 ClassPathXmlApplicationContext 1-5 小段源碼裏屢次調用了getBean()的方法,咱們常常經過這個方法從beanFactory裏獲取bean實例,而bean的初始化細節也在這個方法裏實現了。本文重點解析getBean()方法。java

AbstractBeanFactory#getBean()

public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
		return doGetBean(name, requiredType, null, false);
	}
	// L235
	@SuppressWarnings("unchecked")
	protected <T> T doGetBean(
			final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
			throws BeansException {

		final String beanName = transformedBeanName(name);
		Object bean;

		// 從手動註冊的單例緩存裏取出相關實例在下面的1-0展開細說
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
		    //建立實例的第一種方式:正在建立的共享單例實例不爲空且是無參數的狀況(此時的單例對象並無真正實例化完畢,僅僅是提早曝光,解決循環依賴的策略)
			...//打印相關日誌,略
			 // 下面這個方法:若是是普通 Bean 的話,直接返回 sharedInstance,
            // 若是是 FactoryBean 的話,返回它建立的那個實例對象 詳見1-1
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		else {
		    //建立實例的第二種方式
			// 當前線程已經建立過了此 beanName 的 prototype 類型的 bean,那麼拋異常.能調用到這裏的確定都是單例的
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			BeanFactory parentBeanFactory = getParentBeanFactory();
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// 檢查當前父bean工廠是否存在該bean實例,若是不存在就遞歸調用直到有實例返回
				String nameToLookup = originalBeanName(name);
				if (args != null) {
					// 有參數,這裏不展開詳說
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else {
					// 無參數建立實例
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
			}

			if (!typeCheckOnly) {
			    //將beanName放入alreadyCreated,標識其實例已經建立
				markBeanAsCreated(beanName);
			}

			try {
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);

				// Guarantee initialization of beans that the current bean depends on.
				String[] dependsOn = mbd.getDependsOn();
				if (dependsOn != null) {
					for (String dep : dependsOn) {
						if (isDependent(beanName, dep)) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
						}
						registerDependentBean(dep, beanName);
						getBean(dep);
					}
				}

				// Create bean instance.
				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
						@Override
						public Object getObject() throws BeansException {
							try {
							    //這裏是第二種建立bean實例的方式,1-2展開詳說
								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;
							}
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}
                //非單例狀況,忽略
				else if (mbd.isPrototype()) {
				    ...
				}

				else {
				    ...
				}
			}
			catch (BeansException ex) {
				cleanupAfterBeanCreationFailure(beanName);
				throw ex;
			}
		}

		// Check if required type matches the type of the actual bean instance.
		if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
			try {
				return getTypeConverter().convertIfNecessary(bean, requiredType);
			}
			catch (TypeMismatchException ex) {
				...
			}
		}
		return (T) bean;
	}
複製代碼

1-0 getSingleton(beanName);

這裏的getSingleton()調用了AbstractBeanFactory父類DefaultSingletonBeanRegistry#getSingleton()方法。spring

在此以前咱們先了解一下spring單例的三級緩存緩存

/** 已實例好單例對象緩存 爲了方便理解稱爲一級緩存(下同)*/
private final Map singletonObjects = new ConcurrentHashMap(256);
/** 提早曝光的單例對象緩存(還沒有實例完) 二級緩存*/
private final Map earlySingletonObjects = new HashMap(16);
/** 單例對象工廠緩存 三級緩存*/
private final Map> singletonFactories = new HashMap>(16);

複製代碼

DefaultSingletonBeanRegistry.java L172安全

public Object getSingleton(String beanName) {
	return getSingleton(beanName, true);
}
/**
 * Return the (raw) singleton object registered under the given name.
 * Checks already instantiated singletons and also allows for an early
 * reference to a currently created singleton (resolving a circular reference).
 * 大致意思是:返回一個以給定名稱註冊的單例對象,檢查已經實例好的單例池子,同時也容許對當前對象的引用
 */
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    //單例對象的cache
	Object singletonObject = this.singletonObjects.get(beanName);
	if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
		//一級緩存裏沒有該對象而且此beanName正在建立過程當中纔會進來,由於正在建立的bean也許會在二級緩存裏
		synchronized (this.singletonObjects) {
		    //二級緩存中取
			singletonObject = this.earlySingletonObjects.get(beanName);
			if (singletonObject == null && allowEarlyReference) {
			    //若是二級緩存裏沒有就從三級緩存裏取
				ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
				if (singletonFactory != null) {
				    //三級緩存裏不爲空就將其放入二級緩存裏,並將其從三級緩存裏移除
					singletonObject = singletonFactory.getObject();
					this.earlySingletonObjects.put(beanName, singletonObject);
					this.singletonFactories.remove(beanName);
				}
			}
		}
	}
	return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
複製代碼

到這裏已經把spring 單例的三級緩存說完了,這三個緩存是spring處理循環依賴的重要依據,有興趣的話能夠看我以前的文章《spring是如何解決循環依賴的?》bash

1-1 getObjectForBeanInstance(sharedInstance, name, beanName, null)第一種建立bean實例的方式

AbstractBeanFactory#getObjectForBeanInstance() L1607app

/**
 * Get the object for the given bean instance, either the bean
 * instance itself or its created object in case of a FactoryBean.
 * 下面這個方法:若是是普通 Bean 的話,直接返回 sharedInstance,
 * 若是是 FactoryBean 的話,返回它建立的那個實例對象
 */
protected Object getObjectForBeanInstance(
		Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {

	// Don't let calling code try to dereference the factory if the bean isn't a factory.
	//若是這個bean不是工廠bean,直接拋異常,不讓其調用者撤銷引用工廠
	if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
	   //name以&開頭而且bean實例不屬於工廠bean,直接拋異常
		throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
	}

	// 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. if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) { //①若是bean實例不是工廠bean,名稱是以&開頭,直接放回bean實例 //②若是bean實例是工廠bean,名稱不是以&開頭,直接放回bean實例 return beanInstance; } Object object = null; if (mbd == null) { //從factoryBeanObjectCache緩存裏取 object = getCachedObjectForFactoryBean(beanName); } if (object == null) { // Return bean instance from factory. FactoryBean<?> factory = (FactoryBean<?>) beanInstance; if (mbd == null && containsBeanDefinition(beanName)) { //將該類的子類、父類配置信息都集中到rootBeanDefinition裏 mbd = getMergedLocalBeanDefinition(beanName); } boolean synthetic = (mbd != null && mbd.isSynthetic()); //下面調用了FactoryBeanRegistrySupport類的getObjectFromFactoryBean(),是從factoryBean裏獲取bean實例的入口 object = getObjectFromFactoryBean(factory, beanName,!synthetic); } return object; } 複製代碼

1-1-0 getObjectFromFactoryBean(factory, beanName,!synthetic)

FactoryBeanRegistrySupport#getObjectFromFactoryBean() L98less

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) {
			    //這裏是實例化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)
				Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
				if (alreadyThere != null) {
					object = alreadyThere;
				}
				else {
					if (object != null && shouldPostProcess) {
						try {
						    //這裏會調用全部BeanPostProcessor#postProcessAfterInitialization的實現方法,這裏不作展開,後續會有文章介紹
							object = postProcessObjectFromFactoryBean(object, beanName);
						}
						catch (Throwable ex) {
							throw new BeanCreationException(beanName,
									"Post-processing of FactoryBean's singleton object failed", ex);
						}
					}
					this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
				}
			}
			return (object != NULL_OBJECT ? object : null);
		}
	}
	else {
	    //非單例場景,這裏不作展開
		...
		return object;
	}
}
複製代碼
1-1-0-0. ==doGetObjectFromFactoryBean(factory, beanName)==

FactoryBeanRegistrySupport#doGetObjectFromFactoryBean() L148ide

private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
			throws BeanCreationException {

		Object object;
		try {
		    //調用java的安全模型來實例化相關類,保證安全
			if (System.getSecurityManager() != null) {
				AccessControlContext acc = getAccessControlContext();
				try {
					object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
						@Override
						public Object run() throws Exception {
								return factory.getObject();
							}
						}, acc);
				}
				catch (PrivilegedActionException pae) {
					throw pae.getException();
				}
			}
			else {
				object = factory.getObject();
			}
		}
		catch (FactoryBeanNotInitializedException ex) {
			throw new BeanCurrentlyInCreationException(beanName, ex.toString());
		}
		catch (Throwable ex) {
			throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
		}

		// Do not accept a null value for a FactoryBean that's not fully // initialized yet: Many FactoryBeans just return null then. if (object == null && isSingletonCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException( beanName, "FactoryBean which is currently in creation returned null from getObject"); } return object; } 複製代碼

這裏只簡單說一下,後面會有專門一篇文章詳細介紹java的安全模型,感興趣的同窗能夠先參考《Java 受權內幕》Java 安全模型介紹》,《Java安全——安全管理器、訪問控制器和類裝載器》先了解一下java的安全模型。post

小結一下,到這裏整個1-1第一種建立bean實例的方法結束了,接下來繼續回到AbstractBeanFactory#doGetBean()方法繼續往下看。ui

1-2 createBean(beanName, mbd, args)第二種建立bean方式

//AbstractAutowireCapableBeanFactory#createBean() L447

/**
 * Central method of this class: creates a bean instance,
 * populates the bean instance, applies post-processors, etc.
 * @see #doCreateBean
 */
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
	 ...
	RootBeanDefinition mbdToUse = mbd;
    
    //經過反射獲取指定beanName的類的字節碼,並將其賦值給mbdToUse的屬性
	Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
	if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
		mbdToUse = new RootBeanDefinition(mbd);
		mbdToUse.setBeanClass(resolvedClass);
	}

	try {
	    //檢查類的方法有無重寫,沒有重寫的設置AbstractBeanDefinition裏Overloaded爲false,避免後續的類型檢查的開銷
		mbdToUse.prepareMethodOverrides();
	}
	catch (BeanDefinitionValidationException ex) {
	    ...
	}

	try {
		// 若是重寫並註冊了BeanPostProcessor,在建立類以前生成類的代理並執行BeanPostProcessor的postProcessAfterInitialization()
		Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
		if (bean != null) {
			return bean;
		}
	}
	catch (Throwable ex) {
		...
	}

	Object beanInstance = doCreateBean(beanName, mbdToUse, args);
	if (logger.isDebugEnabled()) {
	    ...
	}
	return beanInstance;
}
複製代碼
相關文章
相關標籤/搜索