锁定老帖子 主题:Spring源代码解析(一):IOC容器
该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2007-06-26
bennyparlo 写道 3.org.springframework.context.support.AbstractRefreshableApplicationContext中定义DefaultListableBeanFactory成员,同时又通过父类实现DefaultResourceLoader接口,是否意味ApplicationContext本身不是容器的概念,但是他携带或者说绑定了1个BeanFactory的实现.同时ApplicationContext自己本身也是1个Resource资源的解析器? 我想BeanFactory和ApplicationContext还是有区别的,对ApplicationContext,要实现ResourceLoader,MessageSource, ApplicationEventPublisher等这些附加的上下文功能,而BeanFactory就没有这么复杂,因为它不打算为应用提供一个上下文环境,它只提供最基本的IOC服务。 bennyparlo 写道 是否意味ApplicationContext本身不是容器的概念,但是他携带或者说绑定了1个BeanFactory的实现.同时ApplicationContext自己本身也是1个Resource资源的解析器? ApplicationContext不仅仅是容器的概念,它还提供了其他的服务 - 他当然他本身的核心功能是BeanFactory的功能。这个可以从它持有DefaultListableBeanFactory可以看到,它的IOC容器功能是通过持有的这个BeanFactory来实现的,另外再加上继承的DefaultResourceLoader,使得它具备了ResourceLoader的功能。 可以认为ApplicationContext对IOC容器作了进一步的封装,使得应用程序更好使用。 |
|
返回顶楼 | |
发表时间:2007-06-27
同意上述的说法
不过还有1点,可能也是BeanFactory实现与ApplicationContext实现比较明显的区别,BeanFactory在容器启动过程中不会加载所有定义的bean,而ApplicationContext则将加载所有定义的bean和bean所依赖的bean以及他父context. 这个区别在实现上来看,可以从那些代码中体现?? |
|
返回顶楼 | |
发表时间:2007-06-27
BeanDefinitionParserDelegate对所做的,是将xml中的定义封装到BeanDefinition实例对象.那对bean的具体初始化操作以及具体的依赖检查等操作,在哪里做了处理?
|
|
返回顶楼 | |
发表时间:2007-06-27
bennyparlo 写道 同意上述的说法
不过还有1点,可能也是BeanFactory实现与ApplicationContext实现比较明显的区别,BeanFactory在容器启动过程中不会加载所有定义的bean,而ApplicationContext则将加载所有定义的bean和bean所依赖的bean以及他父context. 这个区别在实现上来看,可以从那些代码中体现?? BeanFactory和ApplicationContext的差别体现在对bean的加载处理上,因为它们的具体实现不尽相同,但是不管是 BeanFactory还是ApplicationContext,他们的加载处理都是由BeanDefinitionReader来完成,这个 BeanDefinitionReader完成信息的读取,解析后,最后一步向IOC容器的注册是通过向持有的BeanFactory回调来完成的 - 向IOC容器注册需要实现BeanDefinitionRegistry接口。这个接口在DefaultListBeanFactory里被实现,也就是说ApplicationContext是通过DefaultListBeanFactory来完成向自己持有的IOC容器注册的 - 当然这个IOC容器就是DefaultListBeanFactory。 下面再看加载过程,对ApplicationContext中而言,往往在初始化的时候就加载bean,比如在refresh的时候AbstractApplicationContext: protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws IOException { // 这里使用XMLBeanDefinitionReader来载入bean定义信息的XML文件 XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); //这里配置reader的环境,其中ResourceLoader是我们用来定位bean定义信息资源位置的 ///因为上下文本身实现了ResourceLoader接口,所以可以直接把上下文作为ResourceLoader传递给XmlBeanDefinitionReader beanDefinitionReader.setResourceLoader(this); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); initBeanDefinitionReader(beanDefinitionReader); //这里转到定义好的XmlBeanDefinitionReader中对载入bean信息进行处理 loadBeanDefinitions(beanDefinitionReader); } 这里就为ApplicationContext指定了XmlBeanDefinitionReader,然后是加载过程 - 我们看到这个XmlBeanDefinitionReader持有一个beanFactory, 这个beanFactory是在refresh中得到的: protected final void refreshBeanFactory() throws BeansException { ......... // 这里初始化一个DefaultListBeanFactory并持有,然后把这个beanFactory传到BeanDefinitionReader中让它回调对BeanDefinition在IOC中进行注册。 try { DefaultListableBeanFactory beanFactory = createBeanFactory(); loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } ....... } 而这些步骤往往在XmlBeanFactory中是这样实现的: public class XmlBeanFactory extends DefaultListableBeanFactory { //这里定义需要的BeanDefinitionReader,我们看到的初始化函数中的this,就是把一个DefaultListableBeanFactory放到XmlBeanDefinitionReader中让它回调。 private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this); public XmlBeanFactory(Resource resource) throws BeansException { this(resource, null); } //在初始化函数中调用BeanDefinitionReader来进行加载。 public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException { super(parentBeanFactory); this.reader.loadBeanDefinitions(resource); } } 这些步骤我们在DefaultListableBeanFactory中是看不到的,所以如果要使用 DefaultListableBeanFactory的话,需要编程式的指明BeanDefinitionReader和调用: ClassPathResource res = new ClassPathResource("beans.xml"); DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory); reader.loadBeanDefinitions(res); 如果比较XmlBeanFactory和ApplicationContext,除了XmlBeanFactory不具备那些ResourceLoader和ApplicationEvent这些特定的上下文能力之外,他们持有的IOC容器和加载过程是一样的。 所以BeanDefinitionReader是一个比较重要的类,BeanFactory只维护自己持有的IOC容器,其他都不管,不管你的定义从哪里来,怎么来。 |
|
返回顶楼 | |
发表时间:2007-06-27
jiwenke 写道 bennyparlo 写道 同意上述的说法
不过还有1点,可能也是BeanFactory实现与ApplicationContext实现比较明显的区别,BeanFactory在容器启动过程中不会加载所有定义的bean,而ApplicationContext则将加载所有定义的bean和bean所依赖的bean以及他父context. 这个区别在实现上来看,可以从那些代码中体现?? BeanFactory和ApplicationContext的差别体现在对bean的加载处理上,因为它们的具体实现不尽相同,但是不管是 BeanFactory还是ApplicationContext,他们的加载处理都是由BeanDefinitionReader来完成,这个 BeanDefinitionReader完成信息的读取,解析后,最后一步向IOC容器的注册是通过向持有的BeanFactory回调来完成的 - 向IOC容器注册需要实现BeanDefinitionRegistry接口。这个接口在DefaultListBeanFactory里被实现,也就是说ApplicationContext是通过DefaultListBeanFactory来完成向自己持有的IOC容器注册的 - 当然这个IOC容器就是DefaultListBeanFactory。 下面再看加载过程,对ApplicationContext中而言,往往在初始化的时候就加载bean,比如在refresh的时候AbstractApplicationContext: protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws IOException { // 这里使用XMLBeanDefinitionReader来载入bean定义信息的XML文件 XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); //这里配置reader的环境,其中ResourceLoader是我们用来定位bean定义信息资源位置的 ///因为上下文本身实现了ResourceLoader接口,所以可以直接把上下文作为ResourceLoader传递给XmlBeanDefinitionReader beanDefinitionReader.setResourceLoader(this); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); initBeanDefinitionReader(beanDefinitionReader); //这里转到定义好的XmlBeanDefinitionReader中对载入bean信息进行处理 loadBeanDefinitions(beanDefinitionReader); } 这里就为ApplicationContext指定了XmlBeanDefinitionReader,然后是加载过程 - 我们看到这个XmlBeanDefinitionReader持有一个beanFactory, 这个beanFactory是在refresh中得到的: protected final void refreshBeanFactory() throws BeansException { ......... // 这里初始化一个DefaultListBeanFactory并持有,然后把这个beanFactory传到BeanDefinitionReader中让它回调对BeanDefinition在IOC中进行注册。 try { DefaultListableBeanFactory beanFactory = createBeanFactory(); loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } ....... } 而这些步骤往往在XmlBeanFactory中是这样实现的: public class XmlBeanFactory extends DefaultListableBeanFactory { //这里定义需要的BeanDefinitionReader,我们看到的初始化函数中的this,就是把一个DefaultListableBeanFactory放到XmlBeanDefinitionReader中让它回调。 private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this); public XmlBeanFactory(Resource resource) throws BeansException { this(resource, null); } //在初始化函数中调用BeanDefinitionReader来进行加载。 public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException { super(parentBeanFactory); this.reader.loadBeanDefinitions(resource); } } 这些步骤我们在DefaultListableBeanFactory中是看不到的,所以如果要使用 DefaultListableBeanFactory的话,需要编程式的指明BeanDefinitionReader和调用: ClassPathResource res = new ClassPathResource("beans.xml"); DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory); reader.loadBeanDefinitions(res); 如果比较XmlBeanFactory和ApplicationContext,除了XmlBeanFactory不具备那些ResourceLoader和ApplicationEvent这些特定的上下文能力之外,他们持有的IOC容器和加载过程是一样的。 所以BeanDefinitionReader是一个比较重要的类,BeanFactory只维护自己持有的IOC容器,其他都不管,不管你的定义从哪里来,怎么来。 但是上述的这些过程只是加载资源然后将每1个bean定义封装到BeanDefiniton中,最后将所有BeanDefiniton存放到map中,如: /** Map of bean definition objects, keyed by bean name */ private final Map beanDefinitionMap = new HashMap(); /** List of bean definition names, in registration order */ private final List beanDefinitionNames = new ArrayList(); 可以说这里的map才是容器的核心部分.但是这里的map仅仅存放了定义级别的bean,而要获取bean的实例对象,还有个复杂的过程,这个过spring如何来处理的? |
|
返回顶楼 | |
发表时间:2007-06-27
bennyparlo 写道 BeanDefinitionParserDelegate对所做的,是将xml中的定义封装到BeanDefinition实例对象.那对bean的具体初始化操作以及具体的依赖检查等操作,在哪里做了处理?
具体要到BeanDefinitionParserDelegate中去看看,这个BeanDefinitionParserDelegate是根据Spring的bean定义规则生成BeanDefinition的主要地方: public AbstractBeanDefinition parseBeanDefinitionElement( Element ele, String beanName, BeanDefinition containingBean) { //这里从已经解析好的DOM中取得element的属性,确定bean实例化使用的类名。 String className = null; if (ele.hasAttribute(CLASS_ATTRIBUTE)) { className = ele.getAttribute(CLASS_ATTRIBUTE); } String parent = null; if (ele.hasAttribute(PARENT_ATTRIBUTE)) { parent = ele.getAttribute(PARENT_ATTRIBUTE); } try { this.parseState.push(new BeanEntry(beanName)); //这里是根据得到的类名,去实例化bean对象的地方,注意bean对象不等于BeanDefinition,bean对象只是使用简单的反射机制去得到的一个普通JAVA对象,而BeanDefinition还持有了许多定义信息,bean对象是BeanDefinition持有信息的一部分。 AbstractBeanDefinition bd = BeanDefinitionReaderUtils.createBeanDefinition( parent, className, getReaderContext().getReader().getBeanClassLoader()); //下面是许多对Spring定义的bean定义规则的处理,处理结果会反映在BeanDefinition对象中,比如Singleton等各种配置属性 // 最后返回一个BeanDefinition,这是IOC容器操作bean的基本单元,也就是bean在IOC容器中的基本表现。 if (ele.hasAttribute(SCOPE_ATTRIBUTE)) { // Spring 2.0 "scope" attribute bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE)); if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) { error("Specify either 'scope' or 'singleton', not both", ele); } } else if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) { // Spring 1.x "singleton" attribute bd.setSingleton(TRUE_VALUE.equals(ele.getAttribute(SINGLETON_ATTRIBUTE))); } ......... return bd; ......... } 至于具体的bean的JAVA对象,只是在BeanDefinition中的一个属性,这个对象的生成是在生成BeanDefinition的时候生成的: public static AbstractBeanDefinition createBeanDefinition( String parent, String className, ClassLoader classLoader) throws ClassNotFoundException { //这里确定BeanDefinition的两种类型,RootBeanDefinition或者是ChildBeanDefinition AbstractBeanDefinition bd = null; if (parent != null) { bd = new ChildBeanDefinition(parent); } else { bd = new RootBeanDefinition(); } if (className != null) { if (classLoader != null) { //这里通过定义的class名字和类装载器通过反射机制生成需要的JAVA对象。 //把这个对象保存到BeanDefinition中去,然后返回生成的BeanDefinition bd.setBeanClass(ClassUtils.forName(className, classLoader)); } else { bd.setBeanClassName(className); } } return bd; } 这个BeanDefnition持有了和bean相关的所有配置信息,对于依赖检查和DI的实现, 现在还搞不太明白,也就是说Spring IOC容器是怎样管理bean之间的依赖关系的? - 这个应该是IOC的核心功能。 - 这个要好好看看代码才行。 |
|
返回顶楼 | |
发表时间:2007-06-28
bennyparlo 写道 但是上述的这些过程只是加载资源然后将每1个bean定义封装到BeanDefiniton中,最后将所有BeanDefiniton存放到map中,如: /** Map of bean definition objects, keyed by bean name */ private final Map beanDefinitionMap = new HashMap(); /** List of bean definition names, in registration order */ private final List beanDefinitionNames = new ArrayList(); 可以说这里的map才是容器的核心部分.但是这里的map仅仅存放了定义级别的bean,而要获取bean的实例对象,还有个复杂的过程,这个过spring如何来处理的? 同意! 这里应该涉及到Spring IOC容器的核心了,它把用户定义的bean封装成BeanDefinition,然后放到这个BeanDefinitionMap中去 - 一个bean定义对应一个BeanDefintion,但是这些bean之间的依赖关系是怎样管理和怎样实现注入的? - 这是个很好的问题,要再去研究研究代码啦:) |
|
返回顶楼 | |
发表时间:2007-06-28
bennyparlo 写道 BeanDefinitionParserDelegate对所做的,是将xml中的定义封装到BeanDefinition实例对象.那对bean的具体初始化操作以及具体的依赖检查等操作,在哪里做了处理? 我在loadBeanDefinitions中没有找到依赖注入的地方,只看到生成BeanDefinition的时候会对一些属性进行设置,比如setPropertyValue - 这个PropertyValue里面会有持有RuntimeReferenceBean - 应该持有的是在IOC容器里面已经有的bean的信息-因为是单例所以在IOC容器里应该只有一个BeanDefinition和一个对象实例,但这个只是索引,没有看到怎样在BeanDefinition中的source对象中注入需要的Property.
哪位一起来研究看看 ? |
|
返回顶楼 | |
发表时间:2007-06-28
jiwenke 写道 bennyparlo 写道 BeanDefinitionParserDelegate对所做的,是将xml中的定义封装到BeanDefinition实例对象.那对bean的具体初始化操作以及具体的依赖检查等操作,在哪里做了处理? 我在loadBeanDefinitions中没有找到依赖注入的地方,只看到生成BeanDefinition的时候会对一些属性进行设置,比如setPropertyValue - 这个PropertyValue里面会有持有RuntimeReferenceBean - 应该持有的是在IOC容器里面已经有的bean的信息-因为是单例所以在IOC容器里应该只有一个BeanDefinition和一个对象实例,但这个只是索引,没有看到怎样在BeanDefinition中的source对象中注入需要的Property.
哪位一起来研究看看 ? 在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory中 /** * Central method of this class: creates a bean instance, * populates the bean instance, applies post-processors, etc. * <p>Differentiates between default bean instantiation, use of a * factory method, and autowiring a constructor. * @see #instantiateBean * @see #instantiateUsingFactoryMethod * @see #autowireConstructor */ protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException { // 初始化被依赖的bean实例 if (mbd.getDependsOn() != null) { for (int i = 0; i < mbd.getDependsOn().length; i++) { getBean(mbd.getDependsOn()[i]); } } if (logger.isDebugEnabled()) { logger.debug("Creating instance of bean '" + beanName + "' with merged definition [" + mbd + "]"); } // 判断当前bean的对象是否已经存在 Class beanClass = resolveBeanClass(mbd, beanName); // Prepare method overrides. try { mbd.prepareMethodOverrides(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName, "Validation of method overrides failed", ex); } String errorMessage = null; try { // Instantiate the bean. errorMessage = "BeanPostProcessor before instantiation of bean failed"; // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. if (beanClass != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { Object bean = applyBeanPostProcessorsBeforeInstantiation(beanClass, beanName); if (bean != null) { bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); return bean; } } // Instantiate the bean. errorMessage = "Instantiation of bean failed"; BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { synchronized (getSingletonMutex()) { instanceWrapper = (BeanWrapper) this.factoryBeanInstanceCache.remove(beanName); } } if (instanceWrapper == null) { instanceWrapper = createBeanInstance(beanName, mbd, args); } Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null); // Eagerly cache singletons to be able to resolve circular references // even when triggered by lifecycle interfaces like BeanFactoryAware. if (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)) { if (logger.isDebugEnabled()) { logger.debug("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } addSingleton(beanName, bean); } // Initialize the bean instance. errorMessage = "Initialization of bean failed"; // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the // state of the bean before properties are set. This can be used, for example, // to support styles of field injection. boolean continueWithPropertyPopulation = true; if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (Iterator it = getBeanPostProcessors().iterator(); it.hasNext(); ) { BeanPostProcessor beanProcessor = (BeanPostProcessor) it.next(); if (beanProcessor instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) beanProcessor; if (!ibp.postProcessAfterInstantiation(bean, beanName)) { continueWithPropertyPopulation = false; break; } } } } if (continueWithPropertyPopulation) { populateBean(beanName, mbd, instanceWrapper); } Object originalBean = bean; bean = initializeBean(beanName, bean, mbd); if (!this.allowRawInjectionDespiteWrapping && originalBean != bean && mbd.isSingleton() && hasDependentBean(beanName)) { throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans " + getDependentBeans(beanName) + " in its raw version as part of a circular reference, " + "but has eventually been wrapped (for example as part of auto-proxy creation). " + "This means that said other beans do not use the final version of the bean. " + "This is often the result of over-eager type matching - consider using " + "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example."); } // Register bean as disposable, and also as dependent on specified "dependsOn" beans. registerDisposableBeanIfNecessary(beanName, originalBean, mbd); return bean; } catch (BeanCreationException ex) { throw ex; } catch (Throwable ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, errorMessage, ex); } } 当中有些步骤没有完全看明白,不过这里有个populateBean方法 protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) { PropertyValues pvs = mbd.getPropertyValues(); if (bw == null) { if (!pvs.isEmpty()) { throw new BeanCreationException(beanName, "Cannot apply property values to null instance"); } else { // Skip property population phase for null instance. return; } } 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; } boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE); if (hasInstAwareBpps || needsDepCheck) { PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw); if (hasInstAwareBpps) { for (Iterator it = getBeanPostProcessors().iterator(); it.hasNext(); ) { BeanPostProcessor beanProcessor = (BeanPostProcessor) it.next(); if (beanProcessor instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) beanProcessor; pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvs == null) { return; } } } } if (needsDepCheck) { checkDependencies(beanName, mbd, filteredPds, pvs); } } applyPropertyValues(beanName, mbd, bw, pvs); } 我想这里才是解析BeanDefinition对象,并且根据依赖关系以及自动装配方式进行property装载的实现. 然后这里有个类org.springframework.beans.factory.support.BeanDefinitionValueResolver 这里的 public Object resolveValueIfNecessary(String argName, Object value) { // We must check each value to see whether it requires a runtime reference // to another bean to be resolved. if (value instanceof BeanDefinitionHolder) { // Resolve BeanDefinitionHolder: contains BeanDefinition with name and aliases. BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value; return resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition()); } else if (value instanceof BeanDefinition) { // Resolve plain BeanDefinition, without contained name: use dummy name. BeanDefinition bd = (BeanDefinition) value; return resolveInnerBean(argName, "(inner bean)", bd); } else if (value instanceof RuntimeBeanNameReference) { String ref = ((RuntimeBeanNameReference) value).getBeanName(); if (!this.beanFactory.containsBean(ref)) { throw new BeanDefinitionStoreException( "Invalid bean name '" + ref + "' in bean reference for " + argName); } return ref; } else if (value instanceof RuntimeBeanReference) { RuntimeBeanReference ref = (RuntimeBeanReference) value; return resolveReference(argName, ref); } else if (value instanceof ManagedList) { // May need to resolve contained runtime references. return resolveManagedList(argName, (List) value); } else if (value instanceof ManagedSet) { // May need to resolve contained runtime references. return resolveManagedSet(argName, (Set) value); } else if (value instanceof ManagedMap) { // May need to resolve contained runtime references. return resolveManagedMap(argName, (Map) value); } else if (value instanceof ManagedProperties) { Properties original = (Properties) value; Properties copy = new Properties(); for (Iterator it = original.entrySet().iterator(); it.hasNext();) { Map.Entry propEntry = (Map.Entry) it.next(); Object propKey = propEntry.getKey(); Object propValue = propEntry.getValue(); if (propKey instanceof TypedStringValue) { propKey = ((TypedStringValue) propKey).getValue(); } if (propValue instanceof TypedStringValue) { propValue = ((TypedStringValue) propValue).getValue(); } copy.put(propKey, propValue); } return copy; } else if (value instanceof TypedStringValue) { // Convert value to target type here. TypedStringValue typedStringValue = (TypedStringValue) value; try { Class resolvedTargetType = resolveTargetType(typedStringValue); if (resolvedTargetType != null) { return this.beanFactory.doTypeConversionIfNecessary( this.typeConverter, typedStringValue.getValue(), resolvedTargetType, null); } else { // No target type specified - no conversion necessary... return typedStringValue.getValue(); } } catch (Throwable ex) { // Improve the message by showing the context. throw new BeanCreationException( this.beanDefinition.getResourceDescription(), this.beanName, "Error converting typed String value for " + argName, ex); } } else { // No need to resolve value... return value; } } 可能根据property value的不同进行不同的解析 最后 protected void applyPropertyValues(BeanWrapper bw, PropertyValues pv) { // Synchronize if custom editors are registered. // Necessary because PropertyEditors are not thread-safe. if (!this.customEditors.isEmpty()) { synchronized (this.customEditors) { bw.setPropertyValues(pv); } } else { bw.setPropertyValues(pv); } } 将真正的property values绑定到BeanWrapper对象. 以上就是bean依赖装配的大致过程吧 |
|
返回顶楼 | |
发表时间:2007-06-28
不过对于上述的过程中也有问题.
就是说在org.springframework.beans.factory.xml.BeanDefinitonParserDelegate中 public void parsePropertyElement(Element ele, BeanDefinition bd) { String propertyName = ele.getAttribute(NAME_ATTRIBUTE); if (!StringUtils.hasLength(propertyName)) { error("Tag 'property' must have a 'name' attribute", ele); return; } this.parseState.push(new PropertyEntry(propertyName)); try { if (bd.getPropertyValues().contains(propertyName)) { error("Multiple 'property' definitions for property '" + propertyName + "'", ele); return; } Object val = parsePropertyValue(ele, bd, propertyName); PropertyValue pv = new PropertyValue(propertyName, val); parseMetaElements(ele, pv); pv.setSource(extractSource(ele)); bd.getPropertyValues().addPropertyValue(pv); } finally { this.parseState.pop(); } } 这里的property value只是个从xml中解析来的Element(字符流的封装),具体到了装配的时候,确可以被识别不同类型的对象(BeanDefinitionValueResolver.resolveValueIfNecessary()),这个包装的过程,在哪里实现的呢? |
|
返回顶楼 | |