接上篇,进入第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