论坛首页 Java企业应用论坛

Spring源代码解析(一):IOC容器

浏览 143586 次
该帖已经被评为精华帖
作者 正文
   发表时间: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容器作了进一步的封装,使得应用程序更好使用。
0 请登录后投票
   发表时间:2007-06-27  
同意上述的说法

不过还有1点,可能也是BeanFactory实现与ApplicationContext实现比较明显的区别,BeanFactory在容器启动过程中不会加载所有定义的bean,而ApplicationContext则将加载所有定义的bean和bean所依赖的bean以及他父context.

这个区别在实现上来看,可以从那些代码中体现??
0 请登录后投票
   发表时间:2007-06-27  
BeanDefinitionParserDelegate对所做的,是将xml中的定义封装到BeanDefinition实例对象.那对bean的具体初始化操作以及具体的依赖检查等操作,在哪里做了处理?
0 请登录后投票
   发表时间: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容器,其他都不管,不管你的定义从哪里来,怎么来。
0 请登录后投票
   发表时间: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如何来处理的?
0 请登录后投票
   发表时间: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的核心功能。
- 这个要好好看看代码才行。



0 请登录后投票
   发表时间: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之间的依赖关系是怎样管理和怎样实现注入的? - 这是个很好的问题,要再去研究研究代码啦:)
0 请登录后投票
   发表时间:2007-06-28  
bennyparlo 写道
BeanDefinitionParserDelegate对所做的,是将xml中的定义封装到BeanDefinition实例对象.那对bean的具体初始化操作以及具体的依赖检查等操作,在哪里做了处理?
我在loadBeanDefinitions中没有找到依赖注入的地方,只看到生成BeanDefinition的时候会对一些属性进行设置,比如setPropertyValue - 这个PropertyValue里面会有持有RuntimeReferenceBean - 应该持有的是在IOC容器里面已经有的bean的信息-因为是单例所以在IOC容器里应该只有一个BeanDefinition和一个对象实例,但这个只是索引,没有看到怎样在BeanDefinition中的source对象中注入需要的Property.
哪位一起来研究看看 ?
0 请登录后投票
   发表时间: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依赖装配的大致过程吧
0 请登录后投票
   发表时间: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()),这个包装的过程,在哪里实现的呢?
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics