`

Spring的IOC源码解读&UML

阅读更多
<spring.version>4.0.6.RELEASE</spring.version>
这一部分主要记录bean定义的解析和加载,包括注解方式定义的bean。

【UML】
首先以uml展示ioc过程的全貌,为避免干扰,每个类仅表述了核心的属性,方法和方法内的关键代码。
refresh()方法标橙色,是外部调用的入口,如ContextLoaderListener。
标红色的是一些关键属性和实现。

uml连接:http://dl2.iteye.com/upload/attachment/0115/8766/bedf264c-a530-33b3-924a-2b1799eef3ac.png



【代码解读】
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<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
		registerComponents(parserContext.getReaderContext(), beanDefinitions, element);

		return null;
	}

	protected void registerComponents(
			XmlReaderContext readerContext, Set<BeanDefinitionHolder> 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<BeanDefinitionHolder> processorDefinitions =
					AnnotationConfigUtils.registerAnnotationConfigProcessors(readerContext.getRegistry(), source);
			for (BeanDefinitionHolder processorDefinition : processorDefinitions) {
				compositeDef.addNestedComponent(new BeanComponentDefinition(processorDefinition));
			}
		}

		readerContext.fireComponentRegistered(compositeDef);
	}


未完,待续 -=^^=-
  • 大小: 129.9 KB
分享到:
评论

相关推荐

    Spring IOC源码解读

    SpringIOC源码解说,以及对应的代码解读。

    Spring ioc源码解读

    个人整理SpringIOC源码解读,望大婶们指点指点,后续继续添加

    老王读spring-ioc源码分析&amp;测试代码.zip

    老王读 Spring IoC 系列文章的源码分析&测试代码 Spring IoC 源码分析,帮助大家学习 Spring 源码,更加了解 Spring 的底层 博客专栏地址:https://blog.csdn.net/wang489687009/category_11269905.html

    Spring IoC源码深度剖析开源架构源码2021.pdf

    Spring IoC源码深度剖析开源架构源码2021.pdf

    spring_ioc

    这是spring_ioc部分的内容。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。...

    Spring源码分析_Spring_IOC

    Spring源码分析_Spring_IOC

    Spring4 IOC 示例源码

    Spring4 IOC 示例源码, 包含演示代码,以及所有涉及到的jar包。

    基于Maven构建的Spring IoC源码实例

    Spring IoC 入门实例,包括了多种依赖注入方式,适合Spring初学者学习使用。实例里有详细的注释,一看就懂。

    spring ioc和aop原理流程图(详细)

    spring ioc容器初始化流程图 spring ioc容器依赖注入流程图 spring aop实现原理流程图

    Spring AOP IOC源码笔记.pdf

    1.Spring入门和IOC介绍 2.对象依赖 3.AOP入门 4.JDBCTemplate和Spring事务 5.Spring事务原理 6.Spring事务的一个线程安全问题 7.IOC再回顾和面试题 8.AOP再回顾

    Java进阶之SpringIoC源码深度剖析共19页.pd

    Java进阶之SpringIoC源码深度剖析共19页.pdf.zip

    springIOC手写框架分析

    springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC...

    深入解析Spring IoC源码:核心机制与实践应用

    本文深入探讨了Spring框架中IoC容器的源码机制,涵盖了容器的初始化、Bean工厂的实例化、Bean定义的读取及Spring Bean的生命周期管理。通过精细的分析,本文揭示了AnnotationConfigApplicationContext的实例化过程,...

    spring ioc模块手写demo

    spring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demo...

    springIoc实现原理

    spring ioc指的是控制反转,IOC容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。交由Spring容器统一进行管理,从而实现松耦合

    SpringIoc示例代码

    SpringIoc示例代码,SpringIoc示例代码,SpringIoc示例代码,SpringIoc示例代码

    SpringIOC源码.rar

    1、 需要去构造一个Spring容器:ClassPathXmlApplicationContext; 2、 需要注解定义两个注解:@Service、@Resource; 3、 使用反射的手段读取指定目录下的class信息,解析Class信息; 4、 对Class信息的注解做处理...

    spring Ioc容器配置

    spring Ioc容器配置 IOC容器数据源配置 &lt;!-- 配置数据源 --&gt; destroy-method="close"&gt; &lt;value&gt;org.gjt.mm.mysql.Driver &lt;value&gt;jdbc:mysql://localhost:3306/demo &lt;value&gt;root ...

    Spring Ioc源码分析系列--自动注入循环依赖的处理.doc

    Spring Ioc源码分析系列--自动注入循环依赖的处理.doc

    Spring Ioc源码分析系列--@Autowired注解的实现原理.doc

    Spring Ioc源码分析系列--@Autowired注解的实现原理.doc

Global site tag (gtag.js) - Google Analytics