spring IOC加载流程
2016-02-28 01:17
387 查看
看了网上、书上很多对于spring IOC容器加载过程的分析。大多都只是粗略的讲一下加载流程。其实这样也不错,简单粗暴。清晰记得之前和一个前辈交流时他说的一句话:什么设计模式、设计框架都是扯淡,能实现这个功能就是最好的。其实这样的说法是话走偏锋的,为什么要有各种框架、设计模式,主要还是因为没有它们不能够很好的实现功能。就比如说IOC容器加载中常用的FileSystemXmlApplicationContext,这个类到最顶层的BeanFactory接口,之间有8层集成实现关系。为什么只需要一个类行进工作,缺是存在了这么多的集成实现关系呢?其实是为了更好的拓展和兼容,为了更好的解耦。对于这些源码的阅读分析,如果只是在停留在看懂了实现流程的地步上,不会有太多的收获。
一、spring的总体框架:
1、spring的三个主要的部分,beans、context、core:
在这三个主要部分中的核心是什么呢?那就非beans莫属了。spring的核心就是把我们平时使用的对象配置文件化,而配置文件中的对象就是被解析为beans来供开发人员来使用的。要说一个spring是一个舞台剧,那么beans就是一个个演员,没有演员怎么来的舞台剧?bean在spring中的重要性可想而知。而context的作用就是封装一下beans。如果没有context的话,我们每次使用spring的编程模式就一定要使用编程式使用spring的ioc容器了,而有了context只有,使用spring的ioc容器变得简单了许多,可以使用声明式的方式了。那么core的作用是什么呢?其实core就是一个工具类,如果我们想要将其改名为utils其实都是可以的。
2、beans:·
BeanFactory是所有的bean工厂的父接口,bean工厂的继承实现关系很是错综复杂,其中的一条主线继承关系就如下图所示。BeanFactory中定义getBean()等基本方法。而HierachicalBeanFactrory主要是说明Bean工厂是可以继承实现的,所以其中定义了getParentBeanFactory()这个接口。而ConfigurableBeanFactory这个类就是我们常用的bean工厂了。
3、context:
ApplicationContext 是 Context 的顶级父类。如下图:
可以看到Application其实是继承自BeanFactory的。其就是对于BeanFactory环境的一个更好的整合。有了BeanFactory我们可以进行编程式Ioc,那么有了ApplicationContext之后我们就可以使用声明式Ioc了,Context对于各种类型的配置文件的兼容整合大大提升了使用者的使用效率。
Context 作为 Spring 的 Ioc 容器,基本上整合了 Spring 的大部分功能,或者说是大部分功能的基础。
二、容器加载流程:
1、首先看FileSystemApplicationContext这个context容器的使用过程中内部都做了什么:
a、 可以看到FileSystemApplicationContext的类继承关系如下图所示:
FileSystemApplicationContext之上还有AbstractApplicationContext抽象类等等,如此设计的原因就是为了灵活性、解耦的原因。AbstractApplicationContext中增加了context容器相对于beanFactory容器新增加的特性功能,之后AbstractXmlApplicationContext又增加了对于xml配置文件解析的一些特性方法。每一层继承实现的类,都是实现了职责功能的单一性。目前我接触到的类继承设计形式大部分都是一个接口、一个抽象类、一个实现类。如果考虑到拓展性和解耦兼容的话,就要实现多层继承,每一层有多个实现类,就比如AbstractXmlApplicationContet这一层,就有多个实现,有xml配置文件解析功能类,有web数据解析的功能类,等等。每一层的每个实现类都划分出单一职责。
b、FileSystemXmlApplicationContext解析xml配置文件载入IOC容器:
流程图如下:
可以看到,真正对于配置文件的解析是在BeanDefinitionParserDelegate类中的parseBeanDefinitionElement方法来实现的。其中该方法的代码如下:
(1)解析:可以看到parsePropertyElements()等方法就是对于配置文件中property属性的解析。解析到的元素放置在AbstractBeanDefinition中,而AbstractBeanDefinition由BeanDefinitionHolder来持有。
(2)注册:得到了解析信息要怎么来使用呢,从我们平时根据beanName通过getBean()来获取到指定对象的方式,可以看到应该是由一个HashMap来持有的配置文件信息。所以接下来spring IOC做的事就是把解析得到的BeanDefinitionHolder中的信息注册到一个HashMap中去。注册是怎么做的呢?
在DefaultBeanDefinitionDocumentReader中调用BeanDefinitionReaderUtils中的registerBeanDefinition()方法,最终是使用了DefaultListableBeanFactory这个BeanFactory工厂来最总实现了注册。
(3)使用:最后就是如何使用了:通过getBean()方法来调用使用。
四、算了~~ 本来还想继续详细写的,我认怂了~~ 真的好费事!!! 有空继续补充吧。
一、spring的总体框架:
1、spring的三个主要的部分,beans、context、core:
在这三个主要部分中的核心是什么呢?那就非beans莫属了。spring的核心就是把我们平时使用的对象配置文件化,而配置文件中的对象就是被解析为beans来供开发人员来使用的。要说一个spring是一个舞台剧,那么beans就是一个个演员,没有演员怎么来的舞台剧?bean在spring中的重要性可想而知。而context的作用就是封装一下beans。如果没有context的话,我们每次使用spring的编程模式就一定要使用编程式使用spring的ioc容器了,而有了context只有,使用spring的ioc容器变得简单了许多,可以使用声明式的方式了。那么core的作用是什么呢?其实core就是一个工具类,如果我们想要将其改名为utils其实都是可以的。
2、beans:·
BeanFactory是所有的bean工厂的父接口,bean工厂的继承实现关系很是错综复杂,其中的一条主线继承关系就如下图所示。BeanFactory中定义getBean()等基本方法。而HierachicalBeanFactrory主要是说明Bean工厂是可以继承实现的,所以其中定义了getParentBeanFactory()这个接口。而ConfigurableBeanFactory这个类就是我们常用的bean工厂了。
3、context:
ApplicationContext 是 Context 的顶级父类。如下图:
可以看到Application其实是继承自BeanFactory的。其就是对于BeanFactory环境的一个更好的整合。有了BeanFactory我们可以进行编程式Ioc,那么有了ApplicationContext之后我们就可以使用声明式Ioc了,Context对于各种类型的配置文件的兼容整合大大提升了使用者的使用效率。
Context 作为 Spring 的 Ioc 容器,基本上整合了 Spring 的大部分功能,或者说是大部分功能的基础。
二、容器加载流程:
1、首先看FileSystemApplicationContext这个context容器的使用过程中内部都做了什么:
a、 可以看到FileSystemApplicationContext的类继承关系如下图所示:
FileSystemApplicationContext之上还有AbstractApplicationContext抽象类等等,如此设计的原因就是为了灵活性、解耦的原因。AbstractApplicationContext中增加了context容器相对于beanFactory容器新增加的特性功能,之后AbstractXmlApplicationContext又增加了对于xml配置文件解析的一些特性方法。每一层继承实现的类,都是实现了职责功能的单一性。目前我接触到的类继承设计形式大部分都是一个接口、一个抽象类、一个实现类。如果考虑到拓展性和解耦兼容的话,就要实现多层继承,每一层有多个实现类,就比如AbstractXmlApplicationContet这一层,就有多个实现,有xml配置文件解析功能类,有web数据解析的功能类,等等。每一层的每个实现类都划分出单一职责。
b、FileSystemXmlApplicationContext解析xml配置文件载入IOC容器:
流程图如下:
可以看到,真正对于配置文件的解析是在BeanDefinitionParserDelegate类中的parseBeanDefinitionElement方法来实现的。其中该方法的代码如下:
/** * Parse the bean definition itself, without regard to name or aliases. May return * {@code null} if problems occurred during the parsing of the bean definition. */ public AbstractBeanDefinition parseBeanDefinitionElement( Element ele, String beanName, BeanDefinition containingBean) { this.parseState.push(new BeanEntry(beanName)); String className = null; if (ele.hasAttribute(CLASS_ATTRIBUTE)) { className = ele.getAttribute(CLASS_ATTRIBUTE).trim(); } try { String parent = null; if (ele.hasAttribute(PARENT_ATTRIBUTE)) { parent = ele.getAttribute(PARENT_ATTRIBUTE); } AbstractBeanDefinition bd = createBeanDefinition(className, parent); parseBeanDefinitionAttributes(ele, beanName, containingBean, bd); bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT)); parseMetaElements(ele, bd); parseLookupOverrideSubElements(ele, bd.getMethodOverrides()); parseReplacedMethodSubElements(ele, bd.getMethodOverrides()); parseConstructorArgElements(ele, bd); parsePropertyElements(ele, bd); parseQualifierElements(ele, bd); bd.setResource(this.readerContext.getResource()); bd.setSource(extractSource(ele)); return bd; } catch (ClassNotFoundException ex) { error("Bean class [" + className + "] not found", ele, ex); } catch (NoClassDefFoundError err) { error("Class that bean class [" + className + "] depends on not found", ele, err); } catch (Throwable ex) { error("Unexpected failure during bean definition parsing", ele, ex); } finally { this.parseState.pop(); } return null; }
(1)解析:可以看到parsePropertyElements()等方法就是对于配置文件中property属性的解析。解析到的元素放置在AbstractBeanDefinition中,而AbstractBeanDefinition由BeanDefinitionHolder来持有。
(2)注册:得到了解析信息要怎么来使用呢,从我们平时根据beanName通过getBean()来获取到指定对象的方式,可以看到应该是由一个HashMap来持有的配置文件信息。所以接下来spring IOC做的事就是把解析得到的BeanDefinitionHolder中的信息注册到一个HashMap中去。注册是怎么做的呢?
在DefaultBeanDefinitionDocumentReader中调用BeanDefinitionReaderUtils中的registerBeanDefinition()方法,最终是使用了DefaultListableBeanFactory这个BeanFactory工厂来最总实现了注册。
(3)使用:最后就是如何使用了:通过getBean()方法来调用使用。
四、算了~~ 本来还想继续详细写的,我认怂了~~ 真的好费事!!! 有空继续补充吧。
相关文章推荐
- Java调用ffmpeg进行视频转码
- java并发包concurrent翻译及源码分析之:ReadWriteLock
- java38.Socket通信------使用ServerSocket建立聊天服务器---2
- 基于Eclipse的Android开发(一)——创建第一个Android项目
- spring常用事务配置
- 远程debug调试(eclipse)之openstack windows
- pycharm常用设置(keymap设置及eclipse常用快捷键总结)
- JVM:浅析Java虚拟机结构与机制
- spring加载资源文件中classpath*与classpath的区别
- 001Java-IO流的关系
- Eclipse上安装springsource-tool-suite
- 使用Eclipse开发Android源码
- 【慕课笔记】第五章 JAVA中的集合框架(中) 第1节 Map&HashMap简介
- 黑马第一天笔记
- 【JAVA】22、使用return结束一个方法
- (十二)Spring 单元测试
- (十一) Spring 声明式事务
- (十) Spring AOP
- (九)spring JDBC
- (八)Spring 注解配置