Spring中获取一个bean的流程-2

2012/08/29 08:06:40 No Comments

上篇,进入第4节,实质性地创建一个Bean信息。

4 doCreateBean

4.1 首先创建一个原始对象的包装对象,即BeanWrapper,这通过对bean进行包装而来,如下代码所示:

instanceWrapper = createBeanInstance(beanName, mbd, args);

在这个createBeanInstance方法中,首先会创建原始对象,这就有几个策略。如下所示:
如果存在工厂方法,即在xml中定义了factory-method,就会调用工厂方法进行创建,代码如下所示:

if (mbd.getFactoryMethodName() != null) {
			return instantiateUsingFactoryMethod(beanName, mbd, args);
		}

如果已经确认或者解析了候选构造方法,则调用此方法进行创建

if (resolved) {
			if (autowireNecessary) {
				return autowireConstructor(beanName, mbd, null, null);
			}
			else {
				return instantiateBean(beanName, mbd);
			}
		}

如果存在SmartInstantiationAwareBeanPostProcessor并且对象解析出指定的bean Class有候选的构造方法,如在构造方法上追加@Autowired的话,会优化使用这个构造方法。
最后,采用默认的构造策略进行对象创建,如调用Class.newInstance()方法创建。

4.2 允许其他修改beanDefinition,这主要是允许其他组件提供xml不能提供的信息。如使用Annotation增强Bean定义等。这通过类MergedBeanDefinitionPostProcessor来完成,如果容器中提供了此类实现,则会调用进行bean增强。如CommonAnnotationBeanPostProcessor类,会在bean定义中追加如@Resource之类的bean property引用信息。此代码如下所示:

applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
…..方法内部
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
					bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);

4.3 将当前bean放入singletonFactories以处理循环引用。这主要通过singletonFactories和earlySingletonObjects来协作完成,具体情况可以参考Spring如何处理循环引用。代码如下所示:

addSingletonFactory(beanName, new ObjectFactory() {
				public Object getObject() throws BeansException {
					return getEarlyBeanReference(beanName, mbd, bean);
				}
			});

4.4 处理属性信息,这里通过调用populateBean(beanName, mbd, instanceWrapper);正式进入到bean的属性设置阶段。通过将xml定义的中的属性信息进行处理,最终设置到bean上。代码如下所示:

populateBean(beanName, mbd, instanceWrapper);

4.5 调用bean的初始化方法,这里主要通过调用xml上的init-method以及BeanPostProcesor的beforeInit和afterInit以及InitializeBean接口方法等。

exposedObject = initializeBean(beanName, exposedObject, mbd);

4.6 再次处理循环引用,这里再次处理循环引用,避免循环引用错误。此处详见Spring如何处理循环引用

4.7 注册bean的销毁回调方法,在beanFactory中注册销毁通知,以便在容器销毁时,能够做一些后续处理工作。

registerDisposableBeanIfNecessary(beanName, bean, mbd);

5 populateBean

5.1 给InstantiationAwareBeanPostProcessor机会以进行postProcessAfterInstantiation处理。如果此方法返回false,则直接结束属性处理,表示已经由此类完成属性处理,不再需要进行其他处理。不过,此方法一般实现为直接返回相应的bean信息。代码如下所示:

InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
						continueWithPropertyPopulation = false;
						break;
					}

5.2 处理Autowire,这根据bean的定义以处理,看是否进行autoWireByName还是autoWireByType。代码如下所示:

if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
				autowireByName(beanName, mbd, bw, newPvs);
			}
			if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
				autowireByType(beanName, mbd, bw, newPvs);
			}

5.3 给InstantiationAwareBeanPostProcessor机会以处理属性信息,比如在xml中描述了Annotation定义,使用了<context:annotation-config/>,那么就会使用类CommonAnnotationBeanPostProcessor进行注解类属性注入。如下代码所示:

InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;		
				pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);

5.4 进行Bean属性注入检测,这时根据Bean定义中的dependency-check属性对bean的属性注入信息进行检测,如果有些应该注入的值即没有相对应的值,则会进行报错。如下代码所示:

if (needsDepCheck) {
				checkDependencies(beanName, mbd, filteredPds, pvs);
			}

5.5 处理由xml中定义的值,并设置最终信息。这由方法applyPropertyValues(beanName, mbd, bw, pvs)来完成,并且经过以下步骤。

5.5.1 如果属性值信息已经被解析,则直接进行处理。解析即将定义的值转化为正确的类型,如引用信息转换,集合类型转换,基本类型转换等。如下代码所示:

if (mpvs.isConverted()) {
					bw.setPropertyValues(mpvs);
					return;
				}

不过,这一般返回false,则在第一次创建时都没有被解析的。

5.5.2 组装并解析数据信息。这通过新建一个propertyValueList来存储解析过的属性值信息。首先是信息解析,即将属性定义中的值进行解析,如RuntimeBeanReference解析成引用的Bean对象,这里会进行级联获取bean信息,并追加depend信息。这一步只是解析。如下面代码所示:

Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);

解析之后,要进行类型转换工作,因为解析之后的对象可能并不是最终属性所需要的类型(当然可能性很小)。有的数据信息在解析时就被转换了,比如TypedStringValue。类型转换代码如下所示:

convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);

5.5.3 设置属性值信息。这会先将所有值信息传递过去,然后再一个一个进行设置处理,最后根据属性的名称信息,转换成名称路径进行对象属性设置。如下面代码所示:

类AbstractAutowireCapableBeanFactory
bw.setPropertyValues(new MutablePropertyValues(deepCopy));

类AbstractPropertyAccessor
for (PropertyValue pv : propertyValues) {
				setPropertyValue(pv);
			}
类BeanWrapperImpl
		PropertyTokenHolder tokens = getPropertyNameTokens(getFinalPath(nestedBw, propertyName));
		nestedBw.setPropertyValue(tokens, new PropertyValue(propertyName, value));

6 initialzeBean

6.1 调用Bean感知信息,这将针对Bean的类型进行处理,针对BeanNameAware,BeanClassLoaderAware,BeanFactoryAware往bean设置信息。如为当前bean设置当前bean的name。代码如下所示:

invokeAwareMethods(beanName, bean);

6.2 调用postProcessBeforeInitialization方法,这通过由类BeanPostProcessor来在bean调用初始化方法(init方法等)之前进行调用。代码如下所示:

wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
result = beanProcessor.postProcessBeforeInitialization(result, beanName);

6.3 调用bean的初始化方法。这里有两种方法,一种是实现接口InitializingBean,如果实现了接口,那么就调用此接口的afterPropertiesSet方法。第二种是在定义中设置init-method属性,如果有此方法,则调用此方法。代码如下所示:

invokeInitMethods(beanName, wrappedBean, mbd);

6.4 调用bean的postProcessAfterInitialization方法,这通过由类BeanPostProcessor在bean调用初始化方法之后进行调用。代码如下所示:

wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

至此,整个创建过程结束。
相关信息
Spring中获取一个bean的流程-1

转载请标明出处:i flym
本文地址:https://www.iflym.com/index.php/code/201208290002.html

相关文章:

留下足迹