`
zddava
  • 浏览: 243697 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Spring源代码分析 -- IOC容器(四)

阅读更多
接着说IOC容器的实例化Bean的过程,上次说到了#doCreateBean()方法,这个方法的流程很长,本节主要讲的就是它的实现

	protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd,
			final Object[] args) {
		// Spring的低级别JavaBean包装类
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			// 在未完成的FactoryBean实例缓存中获得一个
			instanceWrapper = (BeanWrapper) this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			// 构造BeanWrapper
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}

		// 获得Bean和Bean的类
		final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
		Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);

		// 调用post-processors去修改bean定义
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				mbd.postProcessed = true;
			}
		}

		// 尝试自动解决循环依赖
		// 判断循环依赖的条件是:bean是单例,允许自动解决循环依赖和单例当先在使用中
		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() {
				public Object getObject() throws BeansException {
					//返回一个Bean的代理
					return getEarlyBeanReference(beanName, mbd, bean);
				}
			});
		}

		// 初始化Bean实例
		Object exposedObject = bean;
		try {
			// 属性装配
			populateBean(beanName, mbd, instanceWrapper);
			// Bean初始化
			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);
			}
		}

		// 解决循环依赖
		if (earlySingletonExposure) {
			Object earlySingletonReference = getSingleton(beanName, false);
			if (earlySingletonReference != null) {
				if (exposedObject == bean) {
					exposedObject = earlySingletonReference;
				} else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
					String[] dependentBeans = getDependentBeans(beanName);
					Set actualDependentBeans = new LinkedHashSet(dependentBeans.length);
					for (int i = 0; i < dependentBeans.length; i++) {
						String dependentBean = dependentBeans[i];
						if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
							actualDependentBeans.add(dependentBean);
						}
					}
					if (!actualDependentBeans.isEmpty()) {
						throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been " + "wrapped. 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.");
					}
				}
			}
		}

		registerDisposableBeanIfNecessary(beanName, bean, mbd);

		return exposedObject;
	}


循环依赖的部分比较复杂难懂,这里就先不研究了,这里就主要看一下属性的装配和Bean的初始化过程,对应的两个步骤是

	populateBean(beanName, mbd, instanceWrapper);
	exposedObject = initializeBean(beanName, exposedObject, mbd);


先来看一下#populateBean()

	protected void populateBean(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw) {
		// 属性值
		PropertyValues pvs = mbd.getPropertyValues();

		if (bw == null) {
			if (!pvs.isEmpty()) {
				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"Cannot apply property values to null instance");
			} else {
				// Skip property population phase for null instance.
				return;
			}
		}

		// 是否继续属性组装
		boolean continueWithPropertyPopulation = true;

		// 调用postProcessAfterInstantiation回调
		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(bw.getWrappedInstance(), beanName)) {
						// 如果#postProcessAfterInstantiation()返回false就不再继续属性组装了
						continueWithPropertyPopulation = false;
						break;
					}
				}
			}
		}

		if (!continueWithPropertyPopulation) {
			return;
		}

		// 自动Bean装配
		if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME
				|| mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

			// 按名字自动装配
			if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
				autowireByName(beanName, mbd, bw, newPvs);
			}

			// 按类型自动装配
			if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
				autowireByType(beanName, mbd, bw, newPvs);
			}

			pvs = newPvs;
		}

		// 是否有InstantiationAwareBeanPostProcessors注册
		boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
		// 是否需要依赖检查
		boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);

		if (hasInstAwareBpps || needsDepCheck) {
			PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw);
			// 调用postProcessPropertyValues回调
			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);
	}


这里就不去花费很多时间去了解#applyPropertyValues()的代码了,以后有机会会详细的给出的。

看过了populateBean之后,接着来看一下#initializeBean()方法:

	protected Object initializeBean(String beanName, Object bean, RootBeanDefinition mbd) {
		if (bean instanceof BeanNameAware) {
			// 处理BeanNameAware回调
			((BeanNameAware) bean).setBeanName(beanName);
		}

		if (bean instanceof BeanClassLoaderAware) {
			// 处理BeanClassLoaderAware回调
			((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
		}

		if (bean instanceof BeanFactoryAware) {
			// 处理BeanFactoryAware回调
			((BeanFactoryAware) bean).setBeanFactory(this);
		}

		Object wrappedBean = bean;
		// 调用postProcessBeforeInitialization回调
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
			// 调用初始化方法
			invokeInitMethods(beanName, wrappedBean, mbd);
		} catch (Throwable ex) {
			throw new BeanCreationException((mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}

		if (mbd == null || !mbd.isSynthetic()) {
			// 调用postProcessAfterInitialization回调
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}
		return wrappedBean;
	}


到这里,XMLFactoryBean的处理就大致看完了,这个系列暂时会停一下,因为低估了Spring的源代码复杂度,我的Spring使用经验太少了,看这个Bean实例化的部分还是很吃力的,很多概念还不是很清楚,以后对Spring了解的多了再详细的给出。
分享到:
评论

相关推荐

    Spring.net二----初探IOC容器.rar源代码

    Spring.Demo项目很可能是包含一个简单的Spring.NET应用示例,可能包括了XML配置文件、服务接口和实现类、以及如何使用IoC容器来获取和使用这些对象的代码。通过这个示例,你可以更直观地了解如何在实际项目中运用...

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

    在Spring源代码解析的第一部分,我们将聚焦于IOC容器,特别是BeanFactory接口,它是所有Spring容器的基础。 BeanFactory接口是Spring的基石,它定义了基本的容器操作,如获取Bean、检查Bean是否存在、确定Bean的...

    Spring源代码解析

    Spring源代码解析(一):IOC容器 Spring源代码解析(二):IoC容器在Web容器中的启动 Spring源代码解析(三):Spring JDBC Spring源代码解析(四):Spring MVC Spring源代码解析(五):Spring AOP获取Proxy Spring源...

    spring-demo10-注解-IOC.zip

    注解是Java语言提供的一种元数据机制,允许我们在源代码中嵌入信息,这些信息可以被编译器或者运行时环境解析和使用。Spring框架充分利用了这一特性,提供了一系列注解来简化配置,使得我们可以避免使用XML配置文件...

    Spring源代码解析.rar

    Spring源代码解析1:IOC容器.doc Spring源代码解析2:IoC容器在Web容器中的启动.doc Spring源代码解析3:Spring JDBC .doc Spring源代码解析4:Spring MVC .doc Spring源代码解析5:Spring AOP获取Proxy .doc Spring...

    Spring2.5.6源代码分析(一):IOC容器

    IoC容器是Spring框架的心脏,它负责管理对象的生命周期和依赖关系,使得开发者能够实现松耦合和高可测试性的应用程序。 首先,我们来理解什么是IoC。IoC,也被称为依赖注入(Dependency Injection),是一种设计...

    Spring 源代码解析

    Spring源代码解析1:IOC容器;Spring源代码解析2:IoC容器在Web容器中的启动;Spring源代码解析3:Spring JDBC ; Spring源代码解析4:Spring MVC ;Spring源代码解析5:Spring AOP获取Proxy;Spring源代码解析6:...

    Spring源代码解析(二):IoC容器在Web容器中的启动.doc

    当我们在Web环境中运行Spring应用时,IoC容器需要在Web容器(如Tomcat、Jetty等)中启动并运行。这个过程涉及到一系列的初始化步骤,确保Spring能够正确地与Web容器集成。 首先,`WebApplicationContext`是`...

    Spring-IoC 容器 - v1.01

    Spring支持多种持久化技术,如JDBC、Hibernate、MyBatis等,可以利用IoC容器管理这些DAO对象,使它们能够依赖于事务管理、数据源等服务。 **工厂模式** 工厂模式是一种创建型设计模式,它提供了一种创建对象的最佳...

    spring ioc容器部署实现

    ### Spring IoC容器部署实现详解 #### 一、Spring IoC容器概述 Spring框架的核心特性之一就是Inversion of Control(IoC),也被称为Dependency Injection(DI)。IoC容器是Spring框架的重要组成部分,它负责管理...

    springIOC核心组件分析.vsdx

    spring-context:上下文,即IOC容器 spring-context-support:对IOC的扩展,以及IOC子容器 spring-context-indexer:类管理组件和Classpath扫描 spring-expression:表达式语句 切面编程: spring-aop:面向切面编程,...

    spring-framework-2.5-rc2-with-dependencies\spring-framework-2.5-rc2\spring-framework-2.5-rc2源代码

    通过阅读和学习这些源码,开发者可以了解到Spring如何实现IoC容器、AOP代理、事件机制、任务调度等多个关键功能。同时,这也有助于开发者更好地理解和使用Spring提供的API,以及在实际项目中如何定制和扩展Spring。 ...

    SpringIOC示例源代码

    3. `TestIoC.java`:这是一个关于IoC容器的测试类,它可能使用Spring的ApplicationContext接口来加载bean.xml配置,然后通过容器获取并测试bean实例。 4. `ServiceBean.java`:这可能是一个通用的服务bean,用于...

    spring-webmvc-struts.jar

    例如,`StrutsActionProxy`类是如何拦截Struts的请求,然后通过Spring的IoC容器查找并调用对应的bean方法。同时,源代码中还展示了如何将Struts的配置信息与Spring的bean定义相结合,实现配置的统一管理和重用。 ...

    spring-context-3.2.0 spring-core-3.2.0 等齐全的Spring jar包

    这里提到的是一组完整的Spring库,包括`spring-core`、`spring-context`、`spring-webmvc`、`spring-web`、`spring-beans`、`spring-test`、`spring-jdbc`、`spring-orm`、`spring-aop`和`spring-tx`,它们都是3.2.0...

    spring源代码解析

    2. **Web环境下的IOC容器启动**:"spring源代码解析(二):IOC容器在web中启动.doc"涵盖了在Web应用中初始化Spring容器的过程,包括ApplicationContext的创建、DispatcherServlet的配置以及如何在Web环境中注入bean...

    spring核心技术源代码spring核心技术源代码1-9章

    通过阅读并分析这些源代码,开发者可以更深入地理解Spring框架的工作机制,学习如何有效地使用其特性来提高代码的可维护性和可扩展性。每个章节都会提供实际的示例,帮助开发者将理论知识转化为实践技能。对于想要...

    Spring IoC简单示例-注解配置-Maven构建

    Spring IoC容器通过解析XML配置文件或使用注解来识别对象及其依赖关系,并在运行时自动装配这些对象,这就是依赖注入。 在Spring中,注解配置是取代传统XML配置的一种方式,它使得代码更加简洁、易读。例如,我们...

Global site tag (gtag.js) - Google Analytics