(转)菜鸟分析Spring源代码之 IOC容器的启动
20111225 By Tony
1. 前言
6月份开始,我就打算做一个Android下的快速开发架构。详见以下文章:
http://blog.csdn.net/nanjingjiangbiao/article/details/6557150
其中,我曾设想引入Spring来做整体的基础架构。后来发展到,我想研究研究Spring的底层代码。
只可惜项目太忙,只好先花钱买了本计先生的《Spring技术内幕》一书.
好书啊,好书啊,只可惜我看得头晕晕。从头到尾到处是代码,中文理解写的高深莫测,只可惜一个UML图都没有,真是天书啊天书。
怎么办呢?上网看评论,都说看不懂这本书的人都不是好程序员。
没办法,只好自我分析,自我批判Spring源代码。
2. 从Spring的最简单的Sample说起
上网到处都能抄到,以下这种小sample
- package com.hyron.tony;
- import org.springframework.beans.factory.BeanFactory;
- import org.springframework.beans.factory.xml.XmlBeanFactory;
- import org.springframework.core.io.ClassPathResource;
-
- public class Test {
-
- public static void main(String[] args)throws Exception {
- BeanFactory factory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
- GreetingService greetingService = (GreetingService)factory.getBean("greetingService");
- greetingService.sayGreeting();
- }
-
- }
以上最起码有两个东西我想搞清,
第一, XML文件的解析规则和算法在那里
第二, Object的动态生成在哪里
1. 分析
先上sample的时序图
首先,简单的紧,applicationContext.xml被构造成ClassPathResource对象,代码如下
- public ClassPathResource(String path, ClassLoader classLoader) {
- Assert.notNull(path, "Path must not be null");
- String pathToUse = StringUtils.cleanPath(path);
- if (pathToUse.startsWith("/")) {
- pathToUse = pathToUse.substring(1);
- }
- this.path = pathToUse;
- this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader());
- }
上面完成两个事情,第一是对文件path的编排。第二是,生成一个classloader出来,具体如下:
- public static ClassLoader getDefaultClassLoader() {
- ClassLoader cl = null;
- try {
- cl = Thread.currentThread().getContextClassLoader();
- }
- catch (Throwable ex) {
-
- }
- if (cl == null) {
-
- cl = ClassUtils.class.getClassLoader();
- }
- return cl;
- }
但是,但是。。。。每一个Resource对象都有一个类加载器的变量??
接下来,资源的加载,也就是XML文件的解析,我们在XmlBeanFactory中看到如下代码:
- private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
-
- public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
- super(parentBeanFactory);
- this.reader.loadBeanDefinitions(resource);
- }
委托啊,委托啊,有木有啊有木有。。
XmlBeanFactory聚合了一个XmlBeanDefinitionReader来处理解析的事情。
然后,我们去XmlBeanDefinitionReader看看XML的解析
代码片段:
-
-
- Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
然后,开始读XML文件咯
代码片段:
-
- InputStream inputStream = encodedResource.getResource().getInputStream();
-
- Document doc = this.documentLoader.loadDocument(
- inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware());
-
-
- Element root = doc.getDocumentElement();
- doRegisterBeanDefinitions(root);
下面就所谓的document的登记,这块的代码还是比较有水平的。
代码片段:
-
- 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);
- }
- }
- }
-
-
- private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
- if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
- importBeanDefinitionResource(ele);
- }
- else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
- processAliasRegistration(ele);
- }
- else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
- processBeanDefinition(ele, delegate);
- }
- else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
-
- doRegisterBeanDefinitions(ele);
- }
- }
-
-
-
- public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
- BeanDefinition containingBean, AbstractBeanDefinition bd) {
-
- if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {
-
- bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
- if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
- error("Specify either 'scope' or 'singleton', not both", ele);
- }
- }
- else if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
-
- bd.setScope(TRUE_VALUE.equals(ele.getAttribute(SINGLETON_ATTRIBUTE)) ?
- BeanDefinition.SCOPE_SINGLETON : BeanDefinition.SCOPE_PROTOTYPE);
- }
- else if (containingBean != null) {
-
- bd.setScope(containingBean.getScope());
- }
-
- if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
- bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
- }
-
- String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
- if (DEFAULT_VALUE.equals(lazyInit)) {
- lazyInit = this.defaults.getLazyInit();
- }
- bd.setLazyInit(TRUE_VALUE.equals(lazyInit));
-
- String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
- bd.setAutowireMode(getAutowireMode(autowire));
-
- String dependencyCheck = ele.getAttribute(DEPENDENCY_CHECK_ATTRIBUTE);
- bd.setDependencyCheck(getDependencyCheck(dependencyCheck));
版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/iteye_3829/article/details/82305886
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
-
发表于 2020-02-25 00:38:01
- 阅读 ( 1225 )
- 分类: