`
zddava
  • 浏览: 240742 次
  • 性别: 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.net二----初探IOC容器.rar

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

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

    Spring源代码解析

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

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

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

    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...

    Spring 源代码解析

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

    spring源码分析(1-10)

    Spring源代码解析(二):ioc容器在Web容器中的启动 Spring源代码分析(三):Spring JDBC Spring源代码解析(四):Spring MVC Spring源代码解析(五):Spring AOP获取Proxy Spring源代码解析(六):Spring声明式事务处理...

    springIOC核心组件分析.vsdx

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

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

    NULL 博文链接:https://samsongbest.iteye.com/blog/1501710

    spring源代码解析

    可以通过使用Spring代码声明式的指定在web应用程序启动时载入应用程序上下文(WebApplicationContext),Spring的ContextLoader是提供这样性能的类,我们可以使用 ContextLoaderServlet或者ContextLoaderListener的...

    spring源码分析

    Spring源代码解析(二):ioc容器在Web容器中的启动 3.Spring源代码解析(三):Spring JDBC 4.Spring源代码解析(四):Spring MVC 5.Spring源代码解析(五):Spring AOP获取Proxy 6. Spring源代码解析(六):Spring...

    Spring源码学习文档,绝对值得好好研究~~

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

    springyuanmaaping.zip

    Spring源代码解析2:IoC容器在Web容器中的启动;Spring源代码解析3:Spring JDBC ; Spring源代码解析4:Spring MVC ;Spring源代码解析5:Spring AOP获取Proxy;Spring源代码解析6:Spring声明式事务处理 ; ...

    spring-04-源代码.rar

    使用Spring的IOC完成保存客户的操作: 。 案例需求 相关知识点 案例代码. Spring 整合 WEB 项目 引入 spring-web.jar 包: Spring 中的工厂(容器): BeanFactory(过时): Spring 配置文件中提示的配置

    spring-02-源代码.rar

    使用Spring的IOC完成保存客户的操作: 。 案例需求 相关知识点 案例代码. Spring 整合 WEB 项目 引入 spring-web.jar 包: Spring 中的工厂(容器): BeanFactory(过时): Spring 配置文件中提示的配置

    spring-01-源代码.rar

    使用Spring的IOC完成保存客户的操作: 。 案例需求 相关知识点 案例代码. Spring 整合 WEB 项目 引入 spring-web.jar 包: Spring 中的工厂(容器): BeanFactory(过时): Spring 配置文件中提示的配置

Global site tag (gtag.js) - Google Analytics