1. 程式人生 > >spring原始碼閱讀(1)- ioc依賴注入之bean載入

spring原始碼閱讀(1)- ioc依賴注入之bean載入

還是先看下DefaultListableBeanFactory的類結構圖

 我們從User user = (User) beanFactory.getBean("user");入手進入bean的載入管理流程。

這裡還是堅持走主線的流程,去掉無關的枝葉,儘量讓業務變得簡單。

開始進入程式碼,首先我們跟到AbstractBeanFactory這個類下面的doGetBean

protected <T> T doGetBean(
			final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
			throws BeansException {

		// 快取中獲取到bean結束
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			if (logger.isDebugEnabled()) {
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		else {

				// 載入依賴
				String[] dependsOn = mbd.getDependsOn();
				if (dependsOn != null) {
					for (String dependsOnBean : dependsOn) {
						getBean(dependsOnBean);
						registerDependentBean(dependsOnBean, beanName);
					}
				}

				// 建立bean例項,這裡是我們需要深入剖析的關鍵,注意到這裡有個回撥
				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
						public Object getObject() throws BeansException {
							return createBean(beanName, mbd, args);
                    }
				}

				else if (mbd.isPrototype()) {
					//建立原型例項,這個scope的例項是每次使用每次建立,其實該程式碼前後有個
                    //threadLocal變數,該變數其實是用來控制多執行緒物件例項化安全的
                    //對這個比較感興趣的可以關注一下前後程式碼,我們還是關注大流程
					prototypeInstance = createBean(beanName, mbd, args);
				}

				else {
				}
		}

		return (T) bean;
	}

從摘除枝葉的程式碼可以看出核心流程了,spring原生的scope有singleton和prototype兩種,singleton是建立一次,以後應用每次獲取都是相同的物件,而prototype是每次getBean都建立一個物件。

我們根據上面的特性想一想,singleton肯定是例項化以後由spring容器管理起來了,以後的每次getBean都是獲取相同的物件,管理起來肯定也就是快取起來了,而prototype例項化就spring容器就不管理了,由此弄懂了getSingletion也就瞭解了prototype的例項化了。

我們來看下getSingleton的兩個引數一個是beanName,一個是一個ObjectFactory物件的匿名類物件。

我們進入DefaultSingleTonBeanRegistry中的getSingleton

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
		
		synchronized (this.singletonObjects) {
			Object singletonObject = this.singletonObjects.get(beanName);
			if (singletonObject == null) {
				
                //這裡將正在載入的bean加入到了一個concurrencyHashMap中
				beforeSingletonCreation(beanName);
				//回撥FactoryBean的getObject
				singletonObject = singletonFactory.getObject();
				//從map中移除
				afterSingletonCreation(beanName);
				//這裡就是比getPrototype多的部分,我們想想估計這裡面實現了記憶體管理bean
				addSingleton(beanName, singletonObject);
			}
			return (singletonObject != NULL_OBJECT ? singletonObject : null);
		}
	}

這裡也是首先從快取中獲取例項,如果快取中沒有則需要建立,而建立回調了傳入的ObjectFactory的getObject,建立成功獲取到singletonObject,對於singleton單例的bean,我們還有一個非常重要的操作也就是快取管理,這個部分在addSingleton中實現了。

我們先來看看獲取到bean對於快取的管理吧

protected void addSingleton(String beanName, Object singletonObject) {
		synchronized (this.singletonObjects) {
			this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
			this.singletonFactories.remove(beanName);
			this.earlySingletonObjects.remove(beanName);
			this.registeredSingletons.add(beanName);
		}
	}
//單例物件,beanName和bean例項的對映關係
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(64);
//beanName和建立bean的工廠的對映關係
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);
//存在這裡的物件還是處於建立中,可以獲取到,用於解決迴圈依賴
private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);
//儲存所有已經註冊bean,name的set集合
	private final Set<String> registeredSingletons = new LinkedHashSet<String>(64);

這裡也就是我們分析的最終目的地了,建立的bean被spring容器管理起來了。

不過我們還不能結束,還有不少細節需要我們關心的,比如如何例項化bean的,我們想能在執行期動態例項化物件的我們第一想到的也就是反射了,我們來找找這方面的點,看看spring在建立例項的問題上做了哪些工作,要知道我們能對bean做能多工作呢

我們來看看getObject回撥部分的getObject:createBean

protected abstract Object createBean(String beanName, RootBeanDefinition mbd, Object[] args)
			throws BeanCreationException;

哎呀,這裡我們找到了一個抽象函式,實現留給了子類。具體的實現留給了AbstractAutowireCapableBeanFactory

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

			// 這裡是例項化後置處理器
		Object bean = resolveBeforeInstantiation(beanName, mbd);
		if (bean != null) 
			return bean;

		Object beanInstance = doCreateBean(beanName, mbd, args);
		
		return beanInstance;
	}

這裡提到了一個分支功能點,例項化後置處理器的處理,我們離開主線看看這部分

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.
			if (mbd.hasBeanClass() && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
				bean = applyBeanPostProcessorsBeforeInstantiation(mbd.getBeanClass(), beanName);
				if (bean != null) {
					bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
				}
			}
			mbd.beforeInstantiationResolved = (bean != null);
		}
		return bean;
	}

對於實現了例項化後置處理器的工廠需要執行,applyBeanPostProcessorsBeforeInstantiation(您應該對後置處理器的功能瞭解吧,就當你瞭解了啊^^),這個函式返回bean不為空的化就執行applyBeanPostProcessorsAfterInitialization,在看看執行這個函式之後的一段程式碼如果返回不為空的化就直接返回bean的短路操作,也就是意味著後續不處理了,要知道到目前位置我們還沒有處理類的例項化。我們想想這個留給我們幹啥用,等我分析完aop部分這個功能也就瞭解了。

我們繼續來到主線AbstractAutowireCapableBeanFactory的doCreateBean

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		//例項化bean並返回一個bean的包裝類
		instanceWrapper = createBeanInstance(beanName, mbd, args);
        //從包裝類中獲取bean例項
        final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
		// bean合併後處理,autowired在這裡預解析,這個點我們不討論
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				mbd.postProcessed = true;
			}
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		//注入屬性
		populateBean(beanName, mbd, instanceWrapper);
		if (exposedObject != null) {
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		//註冊disposableBean,如果配置了destroy-method
		registerDisposableBeanIfNecessary(beanName, bean, mbd);
		
		return exposedObject;
	}

這裡基本上就是類似下面這段程式碼

Object object = new Object();
object.setXXX()
object.init-method();

嗯,就是這麼簡單,例項化一個類,注入類中的屬性值,執行一些需要需要執行的方法,然後註冊一個銷燬的時候需要執行的方法,返回物件。

首先我們來看看例項化物件的程式碼吧,我們來看看是不是如我們之前預期的那樣是一段反射的操作。

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
		// 解析出類的class
		Class<?> beanClass = resolveBeanClass(mbd, beanName);

		// 例項化bean
		return instantiateBean(beanName, mbd);
	}

protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
		Object beanInstance;
		//根據不通的例項化策略例項化物件,
		beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
			
		BeanWrapper bw = new BeanWrapperImpl(beanInstance);
		initBeanWrapper(bw);
		return bw;
		
}

這裡做了例項化操作和包裝物件

我們看看例項化部分,這有一個getInstantiationStrategy(),這裡獲取到的是CglibSubclassingInstantiationStrategy,我們再看看instantiate部分

public Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) {
		// 對於有方法需要覆蓋的或替換的需要用cglib動態代理		
        //沒有直接反射
		if (beanDefinition.getMethodOverrides().isEmpty()) {
			Constructor<?> constructorToUse;
			synchronized (beanDefinition.constructorArgumentLock) {
				constructorToUse = (Constructor<?>) beanDefinition.resolvedConstructorOrFactoryMethod;
				if (constructorToUse == null) {
					final Class<?> clazz = beanDefinition.getBeanClass();
				
					return clazz.getDeclaredConstructor((Class[]) null);
						
					constructorToUse =	clazz.getDeclaredConstructor((Class[]) null);
                    //上面幾步就是為了獲取一個constructor構造器
						//通過構造器例項化物件
					beanDefinition.resolvedConstructorOrFactoryMethod = constructorToUse;
					
				
			}
			return BeanUtils.instantiateClass(constructorToUse);
		}
		else {
			// Must generate CGLIB subclass.
			return instantiateWithMethodInjection(beanDefinition, beanName, owner);
		}

public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
			ReflectionUtils.makeAccessible(ctor);
			return ctor.newInstance(args);
		
	}

首先判斷例項化的方式:分為反射例項化和cglib代理例項化,我們暫是不管代理例項化

針對反射例項化我們先獲取了一個構造器這裡我們只是剖析了無參構造器,帶參的構造器還是比較複雜的,然後通過構造器在instantiateClass中執行反射newInstance例項化物件

到這裡物件的例項已經建立完畢了。

我們繼續doCreateBean建立完例項接下來我們到了populateBean(beanName, mbd, instanceWrapper);屬性注入部分,我們來剖析這部分程式碼

protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
		PropertyValues pvs = mbd.getPropertyValues();

		
		//這裡執行了例項化後置處理器的after方法,
        //遍歷所有的後置處理器,如果postProcessAfterInstantiation返回false,屬性注入就不執行了
		boolean continueWithPropertyPopulation = true;
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    //返回失敗,屬性注入結束
					if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
						continueWithPropertyPopulation = false;
						break;
					}
				}
			}
		}
        //短路
		if (!continueWithPropertyPopulation) {
			return;
		}

        //根據注入型別,查詢依賴的bean
		if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
				mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

			// Add property values based on autowire by name if applicable.
			if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
				autowireByName(beanName, mbd, bw, newPvs);
			}

			// Add property values based on autowire by type if applicable.
			if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
				autowireByType(beanName, mbd, bw, newPvs);
			}

			pvs = newPvs;
		}

        //應用postProcessPropertyValues方法
		boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
		boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);

		if (hasInstAwareBpps || needsDepCheck) {
			PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
			if (hasInstAwareBpps) {
				for (BeanPostProcessor bp : getBeanPostProcessors()) {
					if (bp instanceof InstantiationAwareBeanPostProcessor) {
						InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
						pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
					}
				}
			}
		}
        //屬性注入
		applyPropertyValues(beanName, mbd, bw, pvs);
	}

屬性注入的流程:

1、執行例項化後置處理器的postProcessAfterInstantiation

2、根據注入型別提取bean,存入propertyValues

3、應用postProcessPropertyValues,在屬性注入前對物件的最後一次處理機會

4、注入屬性

離開會主線,我們先來看看bean依賴的問題吧

這裡的bean依賴有2個類別分別是:

  1. AUTOWIRE_BY_TYPE、
  2. AUTOWIRE_BY_NAME

兩個類別的目的一樣,但是實現確實差別較大,我們挑一個簡單的看吧,另一個也就理解了,如果確實對這方面實現感興趣可研究

AUTOWIRE_BY_NAME

protected void autowireByName(
			String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

        //查詢需要依賴的屬性
		String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
		for (String propertyName : propertyNames) {
            //根據依賴的屬性名稱執行getBean,這裡也就是一個遞迴了
			Object bean = getBean(propertyName);
            //將獲取的屬性加入
			pvs.add(propertyName, bean);
			registerDependentBean(propertyName, beanName);
				
		}
	}

這裡就是根據beanName從容器中獲取bean,這裡是一個遞迴了,獲取到的屬性加入pvs。AUTOWI're_BYNAME就是這麼簡單。

然後就是

if (pvs == null || pvs.isEmpty()) {
			return;
		}

		MutablePropertyValues mpvs = null;
		List<PropertyValue> original;

			original = mpvs.getPropertyValueList();

		TypeConverter converter = getCustomTypeConverter();
		if (converter == null) {
			converter = bw;
		}

		BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);

		// Create a deep copy, resolving any references for values.
		List<PropertyValue> deepCopy = new ArrayList<PropertyValue>(original.size());
		boolean resolveNecessary = false;
		for (PropertyValue pv : original) {
			if (pv.isConverted()) {
				deepCopy.add(pv);
			}
			else {
				String propertyName = pv.getName();
				Object originalValue = pv.getValue();
				Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
				Object convertedValue = resolvedValue;
				boolean convertible = bw.isWritableProperty(propertyName) &&
						!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
				if (convertible) {
					convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
				}
				// Possibly store converted value in merged bean definition,
				// in order to avoid re-conversion for every created bean instance.
				if (resolvedValue == originalValue) {
					if (convertible) {
						pv.setConvertedValue(convertedValue);
					}
					deepCopy.add(pv);
				}
				else if (convertible && originalValue instanceof TypedStringValue &&
						!((TypedStringValue) originalValue).isDynamic() &&
						!(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
					pv.setConvertedValue(convertedValue);
					deepCopy.add(pv);
				}
				else {
					resolveNecessary = true;
					deepCopy.add(new PropertyValue(pv, convertedValue));
				}
			}
		}
		if (mpvs != null && !resolveNecessary) {
			mpvs.setConverted();
		}

		// Set our (possibly massaged) deep copy.
		try {
			bw.setPropertyValues(new MutablePropertyValues(deepCopy));
		}
		catch (BeansException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Error setting property values", ex);
		}

這裡實現的功能就是屬性的解析與對應型別的轉換了,加上最後的物件對應屬性的設定。

接下來就是initializeBean了

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
		//呼叫bean實現的相關的aware介面方法
		invokeAwareMethods(beanName, bean);
		

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
            //呼叫後置處理器的applyBeanPostProcessorsBeforeInitialization
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		//這裡面是通過反射呼叫了配置的init-method的方法
		invokeInitMethods(beanName, wrappedBean, mbd);
		

		if (mbd == null || !mbd.isSynthetic()) {
            //呼叫後置處理器的applyBeanPostProcessorsAfterInitialization
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}
		return wrappedBean;
	}

這個裡面就比較簡單了,都是bean生命週期相關的部分介面方法呼叫:

包括後置處理器的

bean相關的BeanNameAware、BeanFactoryAware、BeanClassLoaderAware

applyBeanPostProcessorsBeforeInitialization/applyBeanPostProcessorsAfterInitialization,

afterPropertiesSet()

反射呼叫init-method定義的方法

在就是註冊一個銷燬方法了

protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
		AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
		if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
			if (mbd.isSingleton()) {
				//單例的註冊需要銷燬的bean,此方法中會處理實現DisposableBean的bean
                //並且對所有的bean使用DestructionAwareBeanPostProcessors處理
				registerDisposableBean(beanName,
						new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
			
		}
	}

DefaultSingletonBeanRegistry.registerDisposableBean會將需要執行destory的bean加入到disposableBeans中,容器關閉是會回撥這個Map中的所有銷燬方法。