Spring IOC 加载过程(一 加载xml)

Spring IOC 加载过程

看过很多次Spring容器的源码,每次都没有记录,每次都看到放弃,这次下决心要学习一下源码了,所以写一篇博文来记录,也希望有各路大神来指点不足之处,话不多说,下面开始!

  1. 加载Context
  2. 创建beanFactory
  3. 加载xml

Spring容器结构图
Spring容器结构图

加载Context

我是从一个web程序打断点一步一步跟代码走的,一个web程序的入口应该是web.xml文件

<context-param>
	<param-name>contextConfigLocation</param-name>
	<param-value>classpath:spring-config.xml</param-value>
</context-param>
<!-- 注册Spring ContextLoaderListener -->
<listener>
	<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

web.xml中关于Spring的配置就这么简单,这里我们只看Spring的内容,暂时先不看SpringMVC(web)的内容
然后根据上面的配置进入代码(启动tomcat可以进入)

public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
	public ContextLoaderListener() {
	}
	public ContextLoaderListener(WebApplicationContext context) {
		super(context);
	}
	/**
	 * 初始化Spring容器入口
	 */
	@Override
	public void contextInitialized(ServletContextEvent event) {
		initWebApplicationContext(event.getServletContext());
	}
	@Override
	public void contextDestroyed(ServletContextEvent event) {
		closeWebApplicationContext(event.getServletContext());
		ContextCleanupListener.cleanupAttributes(event.getServletContext());
	}

}

这里就是入口,其实就是执行了一个initWebApplicationContext(event.getServletContext())这个方法。我们进入方法来看:


	public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
		/* 
		 *	WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = "org.springframework.web.context.WebApplicationContext.ROOT" servletContext中没有这个属性
		 */
		if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
			throw new IllegalStateException(
					"Cannot initialize context because there is already a root application context present - " +
					"check whether you have multiple ContextLoader* definitions in your web.xml!");
		}

		Log logger = LogFactory.getLog(ContextLoader.class);
		servletContext.log("Initializing Spring root WebApplicationContext");
		if (logger.isInfoEnabled()) {
			logger.info("Root WebApplicationContext: initialization started");
		}
		//这里记录一个开始时间
		long startTime = System.currentTimeMillis();

		try {
			
			if (this.context == null) { //默认是null
				/*创建web应用上下文
				这里获取到的是默认给的 org.springframework.web.context.support.XmlWebApplicationContext这个类,
				创建web应用下文结束(创建了一个XmlWebApplicationContext对象)*/
				this.context = createWebApplicationContext(servletContext);
			}
			if (this.context instanceof ConfigurableWebApplicationContext) {
				//这里做一下转换
				ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
				if (!cwac.isActive()) {//这里初始值是false
					if (cwac.getParent() == null) { //父容器为空,这里加载回来也是一个空,因为是初次加载还没有父容器
						ApplicationContext parent = loadParentContext(servletContext);
						cwac.setParent(parent);
					}
					//配置刷新Spring容器,这里是这个方法最重要的部分,我们后面解释
					configureAndRefreshWebApplicationContext(cwac, servletContext);
				}
			}
			//把初始化好的Sping容器 放到 sevlet 容器中 这个属性就是上面判断的属性
		   servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
			//获取类加载器
			ClassLoader ccl = Thread.currentThread().getContextClassLoader();
			if (ccl == ContextLoader.class.getClassLoader()) {
				currentContext = this.context;
			}
			else if (ccl != null) {
				currentContextPerThread.put(ccl, this.context);
			}

			if (logger.isDebugEnabled()) {
				logger.debug("Published root WebApplicationContext as ServletContext attribute with name [" +
						WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]");
			}
			if (logger.isInfoEnabled()) {
				long elapsedTime = System.currentTimeMillis() - startTime;
				logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms");
			}

			return this.context;
		}
		catch (RuntimeException ex) {
			logger.error("Context initialization failed", ex);
			
			servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex);
			throw ex;
		}
		catch (Error err) {
			logger.error("Context initialization failed", err);
			servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, err);
			throw err;
		}
	}

下面我们看重点的方法configureAndRefreshWebApplicationContext(cwac, servletContext);这个方法,上代码

protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
		//这里wac.getId() 是类中id属性,内部初始化的方法就是ObjectUtils.identityToString(wac)
		if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
			// The application context id is still set to its original default value
			// -> assign a more useful id based on available information
			String idParam = sc.getInitParameter(CONTEXT_ID_PARAM);//这里没有这个属性,为空
			if (idParam != null) {
				wac.setId(idParam);
			}
			else {
				// Generate default id...
				wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +
						ObjectUtils.getDisplayString(sc.getContextPath()));//设置一个新的id:org.springframework.web.context.WebApplicationContext:
			}
		}

		wac.setServletContext(sc);//将servletContext放入到Spring容器中
		String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);
		if (configLocationParam != null) {
			wac.setConfigLocation(configLocationParam);//设置配置文件路径,classpath:spring-config.xml 这是我们在web.xml中配置的
		}
		ConfigurableEnvironment env = wac.getEnvironment();
		if (env instanceof ConfigurableWebEnvironment) {
			((ConfigurableWebEnvironment) env).initPropertySources(sc, null);
		}

		customizeContext(sc, wac);//这里其实什么都没干,因为没有相应的配置
		//刷新容器。
		wac.refresh();
	}

创建beanFactory

public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// 做准备工作. 这里对一些必要属性做了验证。
			prepareRefresh();
			// 告诉子类刷新内部bean工厂
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
			//准备在这个上下文中使用bean工厂。
			prepareBeanFactory(beanFactory);
			try {
				// 允许在上下文子类中对bean工厂进行后处理。
				postProcessBeanFactory(beanFactory);
				// 调用在上下文中注册为bean的工厂处理器.
				invokeBeanFactoryPostProcessors(beanFactory);
				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);
				// 初始化此上下文的消息源.
				initMessageSource();
				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();
				// Initialize other special beans in specific context subclasses.
				onRefresh();
				// Check for listener beans and register them.
				registerListeners();
				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);
				// Last step: publish corresponding event.
				finishRefresh();
			}
			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}
				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();
				// Reset 'active' flag.
				cancelRefresh(ex);
				// Propagate exception to caller.
				throw ex;
			}
			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
			}
		}
	}

介绍obtainFreshBeanFactory()这个方法

/**
	 * Tell the subclass to refresh the internal bean factory.
	 * @return the fresh BeanFactory instance
	 * @see #refreshBeanFactory()
	 * @see #getBeanFactory()
	 */
	protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		//刷新beanFactory
		refreshBeanFactory();
		//获取beanFactory
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		if (logger.isDebugEnabled()) {
			logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
		}
		return beanFactory;
	}

refreshBeanFactory()

protected final void refreshBeanFactory() throws BeansException {
		//清空原来的beanFactory(),其实这里也没有
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
			//创建beanFactory,这里如果有父容器会加载父容器的beanFactory为当前beanFactory的parentBeanFactory
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			beanFactory.setSerializationId(getId());
			customizeBeanFactory(beanFactory);
			//加载beanDefinitions 这里是对xml尽心校验并解析
			loadBeanDefinitions(beanFactory);
			synchronized (this.beanFactoryMonitor) {
				this.beanFactory = beanFactory;
			}
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}

加载xml

继续从上面的**loadBeanDefinitions(beanFactory)**这个方法开始

//类XmlWebApplicationContext
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
	// 为beanFactory创建一个beanDefinitionReader,用于读取xml,这里是xmlWebApplicatioContext类实现的这个方法,定义的是xmlBeanDefinitionReader
	XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

	// 设置环境,资源加载器,资源处理类
	beanDefinitionReader.setEnvironment(getEnvironment());
	beanDefinitionReader.setResourceLoader(this);
	beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

	// 初始化beanDefinitionReader (这个方法没有实体,留给用户自己扩展)
	initBeanDefinitionReader(beanDefinitionReader);
	// 加载资源
	loadBeanDefinitions(beanDefinitionReader);
}

//加载资源 //类XmlWebApplicationContext
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {
	String[] configLocations = getConfigLocations();
	if (configLocations != null) {
		for (String configLocation : configLocations) {
			//根据配置文件目录加载
			reader.loadBeanDefinitions(configLocation);
		}
	}
}

//根据配置文件目录加载 类AbstractBeanDefinitionReader
public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
	return loadBeanDefinitions(location, null);
}

//这里才是最终实现 类AbstractBeanDefinitionReader
public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {
	//前面设置的RescourceLoader() 就是XmlWebApplicationContext对象 上面的结构图中最终实现了ResourcePatternResolver类
	ResourceLoader resourceLoader = getResourceLoader();
	if (resourceLoader == null) {
		throw new BeanDefinitionStoreException(
				"Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
	}

	if (resourceLoader instanceof ResourcePatternResolver) {
		// Resource pattern matching available.
		try {
			//加载资源
			Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
			//注册bean 这里对xml进行校验 解析 注册bean
			int loadCount = loadBeanDefinitions(resources);
			if (actualResources != null) {
				for (Resource resource : resources) {
					actualResources.add(resource);
				}
			}
			if (logger.isDebugEnabled()) {
				logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
			}
			return loadCount;
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException(
					"Could not resolve bean definition resource pattern [" + location + "]", ex);
		}
	}
	else {
		// Can only load single resources by absolute URL.
		Resource resource = resourceLoader.getResource(location);
		int loadCount = loadBeanDefinitions(resource);
		if (actualResources != null) {
			actualResources.add(resource);
		}
		if (logger.isDebugEnabled()) {
			logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
		}
		return loadCount;
	}

加载xml资源 对xml 校验解析 返回Document

//类AbstractBeanDefinitionReader
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
	Assert.notNull(resources, "Resource array must not be null");
	int counter = 0;
	for (Resource resource : resources) {
		counter += loadBeanDefinitions(resource);
	}
	return counter;
}
/*
* 类XmlBeanDefinitionReader 这里对资源进行了编码 转换为EncodeResource 
* Resource接口和EncodeResource类 都实现了InputStreamSource接口
*/
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
	return loadBeanDefinitions(new EncodedResource(resource));
}
/*
* 类XmlBeanDefinitionReader  
*/
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
		Assert.notNull(encodedResource, "EncodedResource must not be null");
		if (logger.isInfoEnabled()) {
			logger.info("Loading XML bean definitions from " + encodedResource.getResource());
		}

		Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
		//初始化一个Set集合,设置到当前对象中
		if (currentResources == null) {
			currentResources = new HashSet<EncodedResource>(4);
			this.resourcesCurrentlyBeingLoaded.set(currentResources);
		}
		//将encodedResource放到上面初始化的集合中
		if (!currentResources.add(encodedResource)) {
			throw new BeanDefinitionStoreException(
					"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
		}
		try {
			InputStream inputStream = encodedResource.getResource().getInputStream();
			try {
				InputSource inputSource = new InputSource(inputStream);
				if (encodedResource.getEncoding() != null) {
					inputSource.setEncoding(encodedResource.getEncoding());
				}
				//这里对xml转化的流读取解析
				return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
			}
			finally {
				inputStream.close();
			}
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException(
					"IOException parsing XML document from " + encodedResource.getResource(), ex);
		}
		finally {
			currentResources.remove(encodedResource);
			if (currentResources.isEmpty()) {
				this.resourcesCurrentlyBeingLoaded.remove();
			}
		}
	}
/*
* 类XmlBeanDefinitionReader 这里只有两个方法,下面都是处理的异常
*/
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
			throws BeanDefinitionStoreException {
	try {
		Document doc = doLoadDocument(inputSource, resource);
		return registerBeanDefinitions(doc, resource);
	}
	catch (BeanDefinitionStoreException ex) {
		throw ex;
	}
	catch (SAXParseException ex) {
		throw new XmlBeanDefinitionStoreException(resource.getDescription(),
				"Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
	}
	catch (SAXException ex) {
		throw new XmlBeanDefinitionStoreException(resource.getDescription(),
				"XML document from " + resource + " is invalid", ex);
	}
	catch (ParserConfigurationException ex) {
		throw new BeanDefinitionStoreException(resource.getDescription(),
				"Parser configuration exception parsing XML from " + resource, ex);
	}
	catch (IOException ex) {
		throw new BeanDefinitionStoreException(resource.getDescription(),
				"IOException parsing XML document from " + resource, ex);
	}
	catch (Throwable ex) {
		throw new BeanDefinitionStoreException(resource.getDescription(),
				"Unexpected exception parsing XML document from " + resource, ex);
	}
}
/*
* 类XmlBeanDefinitionReader 这里是把xml解析成Document
* 这个方法传的参数很多。包括上面传过来的inputSource 当前对象的资源处理器,错误处理器,xml验证模式,
* 还有一个默认为false的boolean,暂且不管他是干什么的
*/
protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
	return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
			getValidationModeForResource(resource), isNamespaceAware());
}
/*
* 类XmlBeanDefinitionReader
* 获取验证模式
* VALIDATION_AUTO = 1 
*/
protected int getValidationModeForResource(Resource resource) {
	//这里获取的是validationMode这个属性 private int validationMode = VALIDATION_AUTO;默认为1
	int validationModeToUse = getValidationMode();
	if (validationModeToUse != VALIDATION_AUTO) {
		return validationModeToUse;
	}
	int detectedMode = detectValidationMode(resource);//这里根据配置文件获取验证模式
	if (detectedMode != VALIDATION_AUTO) {
		return detectedMode;
	}
	// Hmm, we didn't get a clear indication... Let's assume XSD,
	// since apparently no DTD declaration has been found up until
	// detection stopped (before finding the document's root tag).
	return VALIDATION_XSD;
}

/*
* 类XmlBeanDefinitionReader
* 根据配置文件获取验证模式
*/
protected int detectValidationMode(Resource resource) {
	if (resource.isOpen()) {
		throw new BeanDefinitionStoreException(
				"Passed-in Resource [" + resource + "] contains an open stream: " +
				"cannot determine validation mode automatically. Either pass in a Resource " +
				"that is able to create fresh streams, or explicitly specify the validationMode " +
				"on your XmlBeanDefinitionReader instance.");
	}

	InputStream inputStream;
	try {
		inputStream = resource.getInputStream();
	}
	catch (IOException ex) {
		throw new BeanDefinitionStoreException(
				"Unable to determine validation mode for [" + resource + "]: cannot open InputStream. " +
				"Did you attempt to load directly from a SAX InputSource without specifying the " +
				"validationMode on your XmlBeanDefinitionReader instance?", ex);
	}

	try {
		//根据xml内容 如果第一行有“DOCTYPE”则DTD 否则XSD
		return this.validationModeDetector.detectValidationMode(inputStream);
	}
	catch (IOException ex) {
		throw new BeanDefinitionStoreException("Unable to determine validation mode for [" +
				resource + "]: an error occurred whilst reading from the InputStream.", ex);
	}
}
/*
* 类DefaultDocumentLoader 这里就是解析xml了 最终返回一个Document
*/
public Document loadDocument(InputSource inputSource, EntityResolver entityResolver,
			ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {

	DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);
	if (logger.isDebugEnabled()) {
		logger.debug("Using JAXP provider [" + factory.getClass().getName() + "]");
	}
	DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);
	return builder.parse(inputSource);
}

下面是注册Bean加载到容器中 重点 重点 重点

/*
* 类XmlBeanDefinitionReader
*/
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
	//创建一个DefaultBeanDefinitionDocumentReader对象 实现了BeanDefinitionDocumentReader 接口
	BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
	//getRegistry()这个方法是获取当前对象的beanFactory 
	// getBeanDefinitionCount() 获取beanFactory中beanDefinitionMap()(ConcurrentHashMap) 的size,初始化之前为0
	//这里是获取之前注册的bean
	int countBefore = getRegistry().getBeanDefinitionCount();
	documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
	//返回这次注册的对象的数量
	return getRegistry().getBeanDefinitionCount() - countBefore;
}
/*
* 类DefaultBeanDefinitionDocumentReader
* 注册bean
*/
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
	this.readerContext = readerContext;
	logger.debug("Loading bean definitions");
	//获取根节点
	Element root = doc.getDocumentElement();
	//注册bean
	doRegisterBeanDefinitions(root);
}
/*
*类DefaultBeanDefinitionDocumentReader
* 到这里是不是觉得读到根节点了 终于要开始了? 呵呵 你小看他了,还有延伸
*/
protected void doRegisterBeanDefinitions(Element root) {
	BeanDefinitionParserDelegate parent = this.delegate; //上面方法刚实例化出来,这个属性还是null
	//这里创建一个对象,你可以理解为这个类是真正解析Element的工作类(确实是这样的)
	//创建这个对象的方法后面再看,这里先往下面走
	this.delegate = createDelegate(getReaderContext(), root, parent);
	//刚才创建对象的时候 把root传进去了,这里获取到的值是true
	if (this.delegate.isDefaultNamespace(root)) {
		//PROFILE_ATTRIBUTE = "profile" root节点里没有这个属性 返回false
		String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
		if (StringUtils.hasText(profileSpec)) {
			String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
					profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
			if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
				if (logger.isInfoEnabled()) {
					logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
							"] not matching: " + getReaderContext().getResource());
				}
				return;
			}
		}
	}
	//准备解析xml方法,这个方法是空的 留给用户自己扩展
	preProcessXml(root);
	//解析xml (这里才是重点!!)
	parseBeanDefinitions(root, this.delegate);
	//解析完成,下一步流程 也是空的,留给用户自己扩展
	postProcessXml(root);
	//设置当前对象内的解析对象属性为当前对象的parent 默认为空
	this.delegate = parent;
}

然后我们看这个方法createDelegate(getReaderContext(), root, parent)

/*
* 类DefaultBeanDefinitionDocumentReader 创建解析类
*/
protected BeanDefinitionParserDelegate createDelegate(
	XmlReaderContext readerContext, Element root, BeanDefinitionParserDelegate parentDelegate) {

	BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext);
	delegate.initDefaults(root, parentDelegate);
	return delegate;
}

/*
* BeanDefinitionParserDelegate 初始默认值
*
public void initDefaults(Element root, BeanDefinitionParserDelegate parent) {
	populateDefaults(this.defaults, (parent != null ? parent.defaults : null), root);
	this.readerContext.fireDefaultsRegistered(this.defaults);
}

/*
* BeanDefinitionParserDelegate 设置一些默认值,这里我们都没有配置,基本都是默认的,后面解析的时候会用到
*/
protected void populateDefaults(DocumentDefaultsDefinition defaults, DocumentDefaultsDefinition parentDefaults, Element root) {
	//从参数根节点即<beans>节点中获取default-lazy-init参数  
	String lazyInit = root.getAttribute(DEFAULT_LAZY_INIT_ATTRIBUTE);
	如果lazyInit的值为default,如果parentDefaults不为null则侧其中获取lazyInit,否则设置为false  
	if (DEFAULT_VALUE.equals(lazyInit)) {
		// Potentially inherited from outer <beans> sections, otherwise falling back to false.
		lazyInit = (parentDefaults != null ? parentDefaults.getLazyInit() : FALSE_VALUE);
	}
	defaults.setLazyInit(lazyInit);

	String merge = root.getAttribute(DEFAULT_MERGE_ATTRIBUTE);
	if (DEFAULT_VALUE.equals(merge)) {
		// Potentially inherited from outer <beans> sections, otherwise falling back to false.
		merge = (parentDefaults != null ? parentDefaults.getMerge() : FALSE_VALUE);
	}
	defaults.setMerge(merge);

	String autowire = root.getAttribute(DEFAULT_AUTOWIRE_ATTRIBUTE);
	if (DEFAULT_VALUE.equals(autowire)) {
		// Potentially inherited from outer <beans> sections, otherwise falling back to 'no'.
		autowire = (parentDefaults != null ? parentDefaults.getAutowire() : AUTOWIRE_NO_VALUE);
	}
	defaults.setAutowire(autowire);

	// Don't fall back to parentDefaults for dependency-check as it's no longer supported in
	// <beans> as of 3.0. Therefore, no nested <beans> would ever need to fall back to it.
	defaults.setDependencyCheck(root.getAttribute(DEFAULT_DEPENDENCY_CHECK_ATTRIBUTE));

	if (root.hasAttribute(DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE)) {
		defaults.setAutowireCandidates(root.getAttribute(DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE));
	}
	else if (parentDefaults != null) {
		defaults.setAutowireCandidates(parentDefaults.getAutowireCandidates());
	}

	if (root.hasAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE)) {
		defaults.setInitMethod(root.getAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE));
	}
	else if (parentDefaults != null) {
		defaults.setInitMethod(parentDefaults.getInitMethod());
	}

	if (root.hasAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE)) {
		defaults.setDestroyMethod(root.getAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE));
	}
	else if (parentDefaults != null) {
		defaults.setDestroyMethod(parentDefaults.getDestroyMethod());
	}

	defaults.setSource(this.readerContext.extractSource(root));
}

解析的方法parseBeanDefinitions(root, this.delegate);

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
		if (delegate.isDefaultNamespace(root)) {//这里是true 按根节点来解析
			NodeList nl = root.getChildNodes();//获取子节点列表
			for (int i = 0; i < nl.getLength(); i++) {
				Node node = nl.item(i);
				if (node instanceof Element) {
					Element ele = (Element) node;
					if (delegate.isDefaultNamespace(ele)) {//节点是否是默认命名空间
						parseDefaultElement(ele, delegate);//具体解析 默认命名空间 标签<bean>
					}
					else {
						delegate.parseCustomElement(ele);//具体解析 自定义标签 <context:...
					}
				}
			}
		}
		else {
			delegate.parseCustomElement(root);
		}
	}

具体解析,后面再写。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值