java是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由Sun Microsystems公司于1995年5月推出的Java程序设计语言和Java平台(即JavaEE, JavaME, JavaSE)的总称。本站提供基于Java框架struts,spring,hibernate等的桌面应用、web交互及移动终端的开发技巧与资料

保持永久学习的心态,将成就一个优秀的你,来 继续搞起java知识。

4.0.6.RELEASE
这一部分主要记录bean定义的解析和加载,包括注解方式定义的bean。
【UML】
首先以uml展示ioc过程的全貌,为避免干扰,每个类仅表述了核心的属性,方法和方法内的关键代码。
refresh()方法标橙色,是外部调用的入口,如ContextLoaderListener。
标红色的是一些关键属性和实现。
uml连接:http://dl2.iteye.com/upload/attachment/0115/8766/bedf264c-a530-33b3-924a-2b1799eef3ac.png
Spring的IOC源码解读&UML-飞网
【代码解读】
XmlWebApplicationContext继承了AbstractApplicationContext。AbstractApplicationContext的refresh()方法对外提供访问入口,定义了bean定义的解析,创建和一些过程处理,如aop等。使用方法模版的设计模式,由各子类实现一些过程的细节。

@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				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) {
				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}
		}
	}

在refresh()方法中,obtainFreshBeanFactory()方法负责beanFactory的创建及bean定义的解析逻辑,并让applicationContext持有beanFactory。

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		refreshBeanFactory();
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		if (logger.isDebugEnabled()) {
			logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
		}
		return beanFactory;
	}

refreshBeanFactory()是一个抽象方法,具体实现是由AbstractRefreshableApplicationContext实现的。在这个方法中,如果已经存在beanFactory,则销毁beanFactory持有的bean定义及bean实例,并销毁beanFactory,代码实现上就是附null。然后创建一个新的beanFactory,具体实现类为DefaultListableBeanFactory。

@Override
	protected final void refreshBeanFactory() throws BeansException {
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			beanFactory.setSerializationId(getId());
			customizeBeanFactory(beanFactory);
			loadBeanDefinitions(beanFactory);
			synchronized (this.beanFactoryMonitor) {
				this.beanFactory = beanFactory;
			}
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}

loadBeanDefinitions()方法负责bean定义的解析,在AbstractRefreshableApplicationContext中是个抽象方法,由XmlWebApplicationContext实现。因为我们项目在web.xml配的是XmlWebApplicationContext。在这个方法中,会将beanFacotry以BeanDefinitionRegistry接口的实现放到XmlBeanDefinitionReader中,并让XmlBeanDefinitionReader持有beanFactory,以方便后面解析出beanDefinition后,可以注册到beanFactory中。当然实际持有beanFactory的是XmlBeanDefinitionReader的父类AbstractBeanDefinitionReader,可以参看UML图。

@Override
	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
		// Create a new XmlBeanDefinitionReader for the given BeanFactory.
		XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

		// Configure the bean definition reader with this context's
		// resource loading environment.
		beanDefinitionReader.setEnvironment(getEnvironment());
		beanDefinitionReader.setResourceLoader(this);
		beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

		// Allow a subclass to provide custom initialization of the reader,
		// then proceed with actually loading the bean definitions.
		initBeanDefinitionReader(beanDefinitionReader);
		loadBeanDefinitions(beanDefinitionReader);
	}

根据在web.xml定义的contextConfigLocation,由XmlBeanDefinitionReader开始解析每个配置文件。整体流程的代码实现在XmlBeanDefinitionReader的父类AbstractBeanDefinitionReader中。但bean定义的解析和加载在XmlBeanDefinitionReader中。

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {
		String[] configLocations = getConfigLocations();
		if (configLocations != null) {
			for (String configLocation : configLocations) {
				reader.loadBeanDefinitions(configLocation);
			}
		}
	}

实际的bean定义解析也不是由XmlBeanDefinitionReader完成的,XmlBeanDefinitionReader会创建DefaultBeanDefinitionDocumentReader,并将自己作为XmlReaderContext的一个属性,交由DefaultBeanDefinitionDocumentReader进行处理,并由DefaultBeanDefinitionDocumentReader持有XmlReaderContext。

public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException
		try {
			InputStream inputStream = encodedResource.getResource().getInputStream();
			try {
				InputSource inputSource = new InputSource(inputStream);
				if (encodedResource.getEncoding() != null) {
					inputSource.setEncoding(encodedResource.getEncoding());
				}
				return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
			}
			finally {
				inputStream.close();
			}
		}

	public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		documentReader.setEnvironment(this.getEnvironment());
		int countBefore = getRegistry().getBeanDefinitionCount();
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}

在DefaultBeanDefinitionDocumentReader解析bean定义的过程中,遇到非http://www.springframework.org/schema/beans命名空间的标签,会交由BeanDefinitionParserDelegate 进行解析。BeanDefinitionParserDelegate会持有DefaultBeanDefinitionDocumentReader的readerContext。

BeanDefinitionParserDelegate parent = this.delegate;
		this.delegate = createDelegate(this.readerContext, root, parent);

		preProcessXml(root);
		parseBeanDefinitions(root, this.delegate);
		postProcessXml(root);

		this.delegate = parent;

	protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
		if (delegate.isDefaultNamespace(root)) {
			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);
					}
					else {
						delegate.parseCustomElement(ele);
					}
				}
			}
		}
		else {
			delegate.parseCustomElement(root);
		}
	}

类似于注解和aop等的定义解析,都是由BeanDefinitionParserDelegate完成的,他会根据namespaceUri的不同,找到不同的NameSpaceHandler。查找的工作由readerContext持有的属性NamespaceHandlerResolver完成,对应的实现类是DefaultNamespaceHandlerResolver。而DefaultNamespaceHandlerResolver的创建,是在XMLBeanDefinitionReader在创建XmlReaderContext时,就已经指定的,可参考UML图,或者前面的代码解读。
NameSpaceHandler都放在DefaultNamespaceHandlerResolver的属性handlerMappings中,此处找到的实现类是NamespaceHandlerSupport。

public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
		String namespaceUri = getNamespaceURI(ele);
		NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
		if (handler == null) {
			error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
			return null;
		}
		return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
	}

NamespaceHandlerSupport的属性parsers中存放了所需的BeanDefinitionParser。以注解为例,会找到ComponentScanBeanDefinitionParser,处理注解的bean定义解析,并最终调用readerContext的fireComponentRegistered方法,向eventListener注册componentDefinition。

@Override
	public BeanDefinition parse(Element element, ParserContext parserContext) {
		String[] basePackages = StringUtils.tokenizeToStringArray(element.getAttribute(BASE_PACKAGE_ATTRIBUTE),
				ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);

		// Actually scan for bean definitions and register them.
		ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
		Set beanDefinitions = scanner.doScan(basePackages);
		registerComponents(parserContext.getReaderContext(), beanDefinitions, element);

		return null;
	}

	protected void registerComponents(
			XmlReaderContext readerContext, Set beanDefinitions, Element element) {

		Object source = readerContext.extractSource(element);
		CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), source);

		for (BeanDefinitionHolder beanDefHolder : beanDefinitions) {
			compositeDef.addNestedComponent(new BeanComponentDefinition(beanDefHolder));
		}

		// Register annotation config processors, if necessary.
		boolean annotationConfig = true;
		if (element.hasAttribute(ANNOTATION_CONFIG_ATTRIBUTE)) {
			annotationConfig = Boolean.valueOf(element.getAttribute(ANNOTATION_CONFIG_ATTRIBUTE));
		}
		if (annotationConfig) {
			Set processorDefinitions =
					AnnotationConfigUtils.registerAnnotationConfigProcessors(readerContext.getRegistry(), source);
			for (BeanDefinitionHolder processorDefinition : processorDefinitions) {
				compositeDef.addNestedComponent(new BeanComponentDefinition(processorDefinition));
			}
		}

		readerContext.fireComponentRegistered(compositeDef);
	}

未完,待续 -=^^=-
javaspringiocbean

因为水平有限,难免有疏忽或者不准确的地方,希望大家能够直接指出来,我会及时改正。一切为了知识的分享。

后续会有更多的精彩的内容分享给大家。