Spring 源碼剖析 三、主要邏輯代碼賞析之根據bean的定義來生成bean

  上一節中將瞭如何通過xml文件中讀取到bean的定義,鏈接爲 Spring 二、主要邏輯代碼賞析之獲取bean的定義 ,這一節中,我們將會講述讀取出xml文件後,如何根據bean的定義來最終生成bean。

  首先還是來看一下

ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); 

  初始的時候的refresh() 方法:

  	@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {

			// Prepare this context for refreshing.
			prepareRefresh();
			. . .
			// 此爲獲取一個 DefaultListableBeanFactory 的 beanFactory,並且會生成 XmlBeanDefinitionReader ,從xml文件中讀出beanDefinition並放置到 beanFactory中
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();


			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);
			try {
				. . .

				//  DefaultListableBeanFactory 會在此方法中根據 BeanDefinition 去加載bean的定義。
				finishBeanFactoryInitialization(beanFactory);

				finishRefresh();
			}

			catch (BeansException ex) {
				. . .
				// Propagate exception to caller.
				throw ex;
			}

			finally {

				. . .
			}
		}
	}

可以看到 ,是在 finishBeanFactoryInitialization(beanFactory) 方法中將beanDefinition生成bean的。
下面我們看一下 DefultListableBeanFactory來獲取bean的方法:

	@Override
	public void preInstantiateSingletons() throws BeansException {

		// 得到所有的bean定義的name列表
		List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);

		// 遍歷bean定義name的列表,得到對應的bean定義
		for (String beanName : beanNames) {

			this.logger.debug("beanName 爲" + beanName);

			// 得到bean的定義
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {

				// 如果是工廠類的bean
				if (isFactoryBean(beanName)) {

					final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
					boolean isEagerInit;
					if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
						isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
							@Override
							public Boolean run() {
								return ((SmartFactoryBean<?>) factory).isEagerInit();
							}
						}, getAccessControlContext());
					}
					else {
						isEagerInit = (factory instanceof SmartFactoryBean &&
								((SmartFactoryBean<?>) factory).isEagerInit());
					}

					if (isEagerInit) {


						getBean(beanName);

					}
				}
				
				// 如果不是工廠類的bean,即爲普通bean,則直接調用 getBean() 方法
				else {
					getBean(beanName);
				}
			}
		}


	}

  可以看到,DefultListableBeanFactory會遍歷bean的beanName,然後調用getBean(beanName)方法來獲取到bean。getBean(beanName)即調用的 doGetBean() 方法來獲取到bean。

	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;

		// doGetBean() ,這個方法主要做了兩件事情:
		// 1、判斷是否已存在指定beanName的bean,如果有,直接返回
		// 2、如果沒有,得到其beanDefinition,然後生成bean,放到map中,再返回。


		// 從map中得到bean
		Object sharedInstance = getSingleton(beanName);
		// 如果有,那麼就肯定不用生成了,直接返回
		if (sharedInstance != null && args == null) {
			if (logger.isDebugEnabled()) {
				if (isSingletonCurrentlyInCreation(beanName)) {
					logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				}
				else {
					logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		// 發現如果沒有bean,那麼就得到相應的beanDefinition,然後生成bean
		else {


			// Fail if we're already creating this bean instance:
			// We're assumably within a circular reference.
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			. . .

			// 下面爲獲取單例bean的方法
			try {
				// 根據beanName來獲取到bean的beanDefinition
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);

				. . .

				// 下面爲創建bean的方法
				if (mbd.isSingleton()) {


					// 這裏是實現了 ObjectFactory 這個接口,裏面得到創建的 bean 
					// getSingleton方法會做一些處理在同步塊中判斷是否有無bean,如果沒有,再調用回調獲取到bean,並將bean放到 singletonObjects 中,也就是最後的 beanName - > bean對象 的Map
					sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
						@Override
						public Object getObject() throws BeansException {
							try {
								logger.debug(" createBean,初始化bean所要調用的方法 ");
								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);
				}

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

		. . . 

		return (T) bean;
	}

 createBean(String beanName, RootBeanDefinition mbd, Object[] args)方法,其調用的是  doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) 方法,我們看一下其實現:

	protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {

		// 此爲真正去獲取一個bean的方法,也是可以大致分爲兩步:
		// 1、找到其構造函數與構造函數中要傳入的value,比如constructor.newInstance()。這樣就然後生成bean的對象。相當於 User user = new User(xx,xx)
		// 2、對bean對象中的value進行填充 user.setName(xxx),本質上調用的是method.invoke()方法


		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {

			// 此爲創建bean,但是僅僅是創建bean,裏面的value不填充。因爲要創建,所以 如果construction中有依賴,那麼肯定要先加載 construction 中的依賴,	
            // 如果依賴是bean,那麼就加載要依賴的bean
			instanceWrapper = createBeanInstance(beanName, mbd, args);

		}

		// 此爲得到創建好的bean
		final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
		Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);

		// Allow post-processors to modify the merged bean definition.
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				mbd.postProcessed = true;
			}
		}

		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isDebugEnabled()) {
				logger.debug("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			addSingletonFactory(beanName, new ObjectFactory<Object>() {
				@Override
				public Object getObject() throws BeansException {
					return getEarlyBeanReference(beanName, mbd, bean);
				}
			});
		}


		try {
			
			// bean創建完成後,調用下面的方法根據beanDefinition中定義的value對bean進行填充
			populateBean(beanName, mbd, instanceWrapper);
			
			if (exposedObject != null) {
				exposedObject = initializeBean(beanName, exposedObject, mbd);
			}
		}
		catch (Throwable ex) {
			if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
				throw (BeanCreationException) ex;
			}
			else {
				throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
			}
		}

		. . .

		// Register bean as disposable.
		try {
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
		}

		return exposedObject;
	}

  好,我們首先看一下 createBeanInstance() ,即創建bean的方法:

	protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
		. . .
		// 此爲判斷bean的構造方法中是否需要value的注入,如果有,那麼走 autowireConstructor 方法,先找到value
		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
		if (ctors != null ||
				mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
			return autowireConstructor(beanName, mbd, ctors, args);
		}

		// 如果沒有,直接走 instantiateBean ,直接生成一個bean
		return instantiateBean(beanName, mbd);
	}

  那麼比如是

    <bean id="dependC" class="com.happyheng.bean.DependC">
        <constructor-arg ref="dependA"/>
    </bean>

   那麼肯定需要走 autowireConstructor() ,因爲構造方法裏面有value需要創建。在 autowireConstructor()  中,首先去獲取裏面的value值

	private int resolveConstructorArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw,
			ConstructorArgumentValues cargs, ConstructorArgumentValues resolvedValues) {

		. . . 

		for (ConstructorArgumentValues.ValueHolder valueHolder : cargs.getGenericArgumentValues()) {
			// 遍歷 Constructor 參數
			if (valueHolder.isConverted()) {
				resolvedValues.addGenericArgumentValue(valueHolder);
			}
			else {
				// 得到 Constructor 參數裏面的value
				Object resolvedValue =
						valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue());
				// 得到value之後,替換ConstructorArgumentValues.ValueHolder中的value
				ConstructorArgumentValues.ValueHolder resolvedValueHolder =
						new ConstructorArgumentValues.ValueHolder(resolvedValue, valueHolder.getType(), valueHolder.getName());
				resolvedValueHolder.setSource(valueHolder);
				resolvedValues.addGenericArgumentValue(resolvedValueHolder);
			}
		}

		return minNrOfArgs;
	}

  在獲取value值的時候,有這樣的方法:

	public Object resolveValueIfNecessary(Object argName, Object value) {
		// 如果value是 RuntimeBeanReference ,那麼需要先獲取到這個bean,即如果有,就直接拿到返回,如果沒有,就創建
		if (value instanceof RuntimeBeanReference) {
			RuntimeBeanReference ref = (RuntimeBeanReference) value;
			return resolveReference(argName, ref);
		}

		. . .
		
	}

  所以如果 dependC 的構造函數中有 dependA 的話,那麼需要先生成dependA這個bean,最後再生成 dependC 這個bean 。 

   dependC在獲取到了所有構造函數的值後(即dependA已經生成),會在autowireConstructor() 方法的最後 調用 instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner, final Constructor<?> ctor, Object... args)  方法來傳入Constructor與對應的args利用反射來生成bean。 

   至於前面所說的構造函數中沒有參數的bean,比如:

<bean id="myBean" class="com.happyheng.bean.MyBean"/>

  則直接調用 instantiateBean(beanName, mbd) 方法,其調用了方法:

	@Override
	public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {

		/**
		 * @todo 
		 */
        // 使用了java的反射,先得到bean的Class的 constructor 的方法,然後直接使用 constructor 方法來生成一個bean
		if (bd.getMethodOverrides().isEmpty()) {
			Constructor<?> constructorToUse;
			synchronized (bd.constructorArgumentLock) {
				constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
				if (constructorToUse == null) {

					// 得到bean的Class對象
					final Class<?> clazz = bd.getBeanClass();
					if (clazz.isInterface()) {
						throw new BeanInstantiationException(clazz, "Specified class is an interface");
					}
					try {
						if (System.getSecurityManager() != null) {
							constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor<?>>() {
								@Override
								public Constructor<?> run() throws Exception {
									return clazz.getDeclaredConstructor((Class[]) null);
								}
							});
						}
						else {
							// 得到這個bean的 Constructor 方法
							constructorToUse =	clazz.getDeclaredConstructor((Class[]) null);
						}
						bd.resolvedConstructorOrFactoryMethod = constructorToUse;
					}
					catch (Exception ex) {
						throw new BeanInstantiationException(clazz, "No default constructor found", ex);
					}
				}
			}

			// 將 Constructor 方法傳入到 BeanUtils 來直接生成一個對象即可
			return BeanUtils.instantiateClass(constructorToUse);
		}
		else {
			// Must generate CGLIB subclass.
			return instantiateWithMethodInjection(bd, beanName, owner);
		}
	}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章