1. 程式人生 > >白話Spring原始碼(五):Bean的建立過程

白話Spring原始碼(五):Bean的建立過程

我們知道可以通過name從beanFactory獲取對應bean物件,那bean是怎麼建立的呢?

我們先設想如果我們來建立物件需要哪幾步呢?

1.找到物件的class

2.通過反射建立物件

3.設定物件的屬性值

其實spring建立物件的也是主要分這幾步,下面我們進入原始碼看看吧!

上篇部落格我們瞭解了beanFactory的結構,但那都是介面並沒有具體實現,beanFactory的getBean(String name)是獲取bean例項的方法,他的第一個實現是在AbstractBeanFactory的抽象類裡

AbstractBeanFactory的getBean:

	public Object getBean(String name) throws BeansException {
		String beanName = transformedBeanName(name);//轉換name,主要是對FactoryBean進行處理,下面部落格會講解FactoryBean
		Object sharedInstance = this.singletonCache.get(beanName);//看看單例裡有沒有bean例項,因為單例是先建立好,放到map裡的
		if (sharedInstance != null) {
			if (logger.isDebugEnabled()) {
				logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
			}
			return getObjectForSharedInstance(name, sharedInstance);//如果單列裡有對直接從map中get出來
		}
		else {//如果單例的map裡沒有就建立
			RootBeanDefinition mergedBeanDefinition = null;
			try {
				mergedBeanDefinition = getMergedBeanDefinition(beanName, false);//獲取bean對應的class資訊,class資訊封裝在RootBeanDefinition
			}
			catch (NoSuchBeanDefinitionException ex) {
				if (this.parentBeanFactory != null) {
					return this.parentBeanFactory.getBean(name);//如果當前工廠沒找到class,就從父級的工廠裡找
				}
				throw ex;
			}
			// create bean instance
			if (mergedBeanDefinition.isSingleton()) {//判斷是不是配置成單例,如果是單列,建立好,放到單例的map裡
				synchronized (this.singletonCache) {
					// re-check singleton cache within synchronized block
					sharedInstance = this.singletonCache.get(beanName);
					if (sharedInstance == null) {
						logger.info("Creating shared instance of singleton bean '" + beanName + "'");
						sharedInstance = createBean(beanName, mergedBeanDefinition);
						addSingleton(beanName, sharedInstance);
					}
				}
				return getObjectForSharedInstance(name, sharedInstance);
			}
			else {//如果不是配置成單例,則建立物件
				return createBean(name, mergedBeanDefinition);//建立物件
			}
		}
	}

這裡只是先對name進行轉換(這裡涉及FactoryBean,後面會專門講解),然後從單例的map裡查,如果有則返回,沒有就從xml載入配置的類的資訊,封裝在RootBeanDefinition 裡(以後部落格會分析BeanDefinition),到這裡還是沒講怎麼建立物件,建立過程在createBean(name, mergedBeanDefinition)方法裡,createBean是在AbstractAutowireCapableBeanFactory的抽象類裡實現的。

AbstractAutowireCapableBeanFactory的createBean方法

	protected Object createBean(String beanName, RootBeanDefinition mergedBeanDefinition) throws BeansException {
		if (logger.isDebugEnabled()) {
			logger.debug("Creating instance of bean '" + beanName + "' with merged definition [" + mergedBeanDefinition + "]");
		}

		if (mergedBeanDefinition.getDependsOn() != null) {//判斷是否配置依賴,有則先建立依賴的物件
			for (int i = 0; i < mergedBeanDefinition.getDependsOn().length; i++) {
				// guarantee initialization of beans that the current one depends on
				getBean(mergedBeanDefinition.getDependsOn()[i]);
			}
		}

		BeanWrapper instanceWrapper = null;//BeanWrapper這個是建立物件的包裝類
		if (mergedBeanDefinition.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
				mergedBeanDefinition.hasConstructorArgumentValues()) {//判斷是否通過構造方法建立的,如果是則裝配構造方法引數沒返回BeanWrapper
			instanceWrapper = autowireConstructor(beanName, mergedBeanDefinition);
		}
		else {//如果沒有配置構造方法的引數
			instanceWrapper = new BeanWrapperImpl(mergedBeanDefinition.getBeanClass());//new BeanWrapper
			initBeanWrapper(instanceWrapper);//設定自定義屬性
		}
		Object bean = instanceWrapper.getWrappedInstance();//直接通過無參的方式new物件,好了物件創建出來了

		//如果是單列放到單例的map裡
		if (mergedBeanDefinition.isSingleton()) {
			addSingleton(beanName, bean);
		}

		populateBean(beanName, mergedBeanDefinition, instanceWrapper);//設定物件的屬性

		//判斷是否Aware,這後面會專門講
		try {
			if (bean instanceof BeanNameAware) {
				if (logger.isDebugEnabled()) {
					logger.debug("Invoking setBeanName() on BeanNameAware bean '" + beanName + "'");
				}
				((BeanNameAware) bean).setBeanName(beanName);
			}

			if (bean instanceof BeanFactoryAware) {
				if (logger.isDebugEnabled()) {
					logger.debug("Invoking setBeanFactory() on BeanFactoryAware bean '" + beanName + "'");
				}
				((BeanFactoryAware) bean).setBeanFactory(this);
			}


			bean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);//執行初始化前執行的自定義方法
			invokeInitMethods(bean, beanName, mergedBeanDefinition);//執行初始化方法
			bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);//執行初始化後執行的自定義方法
		}
		catch (InvocationTargetException ex) {
			throw new BeanCreationException(mergedBeanDefinition.getResourceDescription(), beanName,
																			"Initialization of bean failed", ex.getTargetException());
		}
		catch (Exception ex) {
			throw new BeanCreationException(mergedBeanDefinition.getResourceDescription(), beanName,
																			"Initialization of bean failed", ex);
		}
		return bean;
	}

這裡主要講通過RootBeanDefinition來建立物件,設定物件的屬性值。建立物件是通過BeanWrapper 來實現的。其實new物件時很簡單的,就用反射例項無參的構造方法,這裡複雜的是設定物件屬性,設定屬性有兩種方式:構造方法,set方法,其實也是通過反射實現的,具體的實現都在BeanWrapper裡,有興趣的可以自己去看,因為這裡細節太多就不展開了。

 

這裡只講解了怎麼創建出一個物件,但怎麼載入類的資訊的呢?請看下篇部落格。