spring IOC源码分析(1)
1.何谓Spring IOC
何谓Spring IOC?书上谓之“依赖注入”,那何谓“依赖注入”?
作为一个Java程序猿,应该遇到过这样的问题,当你在代码中需要使用某个类提供的功能时,你首先需要new一个对象,给它传递必要的参数,然后才能使用它提供的功能,最后释放对象占用的内存,当然了这个在Java不需要你自己去干了。这也就是说你需要自己去管理变量的整个生命周期,这在大型项目中是很糟糕的。现在好了,有了Spring IOC,这些事情都不需要你去做,你只需要告诉Spring你需要的变量实例,配置其对应关系,Spring就可以讲你依赖的实例注入到你的变量中。
举个现实的例子,在以前大家找对象都是自己去找,自己去处的,现在不一样了,很多人都通过相亲了,这就有了相亲机构,其实这里相亲机构就是一个Spring IOC容器,你想要找对象,然后你就去找相亲机构,在它那里注个册,告诉它你的要求,比如说高矮胖瘦等等,这个时候,相亲机构就从已经在它那注册了的所有女生中(注:这个时候,你跟那些女生都是相亲机构管理的bean对象)找到符合你要求的女生,最后给到你,让你们自己去折腾了……,这也就是所谓的“依赖注入”,也就是Spring IOC的精髓所在。
2 Spring IOC体系结构
Bean工厂
SpringBean的创建是典型的工厂模式,这一系列的Bean工厂,也即IOC容器为开发者管理对象间的依赖关系提供了很多便利和基础服务,在Spring中有许多的IOC容器的实现供用户选择和使用,其相互关系如下:
其中BeanFactory作为最顶层的一个接口类,它定义了IOC容器的基本功能规范,BeanFactory 有三个子类:ListableBeanFactory、HierarchicalBeanFactory 和AutowireCapableBeanFactory。但是从上图中我们可以发现最终的默认实现类是 DefaultListableBeanFactory,他实现了所有的接口。那为何要定义这么多层次的接口呢?查阅这些接口的源码和说明发现,每个接口都有他使用的场合,它主要是为了区分在 Spring 内部在操作过程中对象的传递和转化过程中,对对象的数据访问所做的限制。例如 ListableBeanFactory 接口表示这些 Bean 是可列表的,而 HierarchicalBeanFactory 表示的是这些 Bean 是有继承关系的,也就是每个Bean 有可能有父 Bean。AutowireCapableBeanFactory 接口定义 Bean 的自动装配规则。这四个接口共同定义了 Bean 的集合、Bean 之间的关系、以及 Bean 行为。
Bean的表示
SpringIOC容器管理了我们定义的各种Bean对象及其相互的关系,Bean对象在Spring实现中是以BeanDefinition来描述的,其继承体系如下:
Bean 的解析过程非常复杂,功能被分的很细,因为这里需要被扩展的地方很多,必须保证有足够的灵活性,以应对可能的变化。Bean 的解析主要就是对 Spring 配置文件的解析。这个解析过程主要通过下图中的类完成:
2. 最基本的IOC容器接口:
- 1. public interface BeanFactory {
- 2.
- 3. //这里是对FactoryBean的转义定义,因为如果使用bean的名字检索FactoryBean得到的对象是工厂生成的对象,
- 4. //如果需要得到工厂本身,需要转义
- 5. String FACTORY_BEAN_PREFIX = "&";
- 6.
- 7.
- 8. //这里根据bean的名字,在IOC容器中得到bean实例,这个IOC容器就是一个大的抽象工厂。
- 9. Object getBean(String name) throws BeansException;
- 10.
- 11. //这里根据bean的名字和Class类型来得到bean实例,和上面的方法不同在于它会抛出异常:如果根据名字取得的bean实例的Class类型和需要的不同的话。
- 12. Object getBean(String name, Class requiredType) throws BeansException;
- 13.
- 14. //这里提供对bean的检索,看看是否在IOC容器有这个名字的bean
- 15. boolean containsBean(String name);
- 16.
- 17. //这里根据bean名字得到bean实例,并同时判断这个bean是不是单件
- 18. boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
- 19.
- 20. //这里对得到bean实例的Class类型
- 21. Class getType(String name) throws NoSuchBeanDefinitionException;
- 22.
- 23. //这里得到bean的别名,如果根据别名检索,那么其原名也会被检索出来
- 24. String[] getAliases(String name);
- 25.
- 26. }
在BeanFactory里只对IOC容器的基本行为作了定义,根本不关心你的bean是如何定义怎样加载的。正如我们只关心工厂里得到什么的产品对象,至于工厂是怎么生产这些对象的,这个基本的接口不关心。
而要知道工厂是如何产生对象的,我们需要看具体的IOC容器实现,spring提供了许多IOC容器的实现。比如XmlBeanFactory,ClasspathXmlApplicationContext等。
3. IoC容器的初始化
IoC容器的初始化包括BeanDefinition的Resource定位、载入和注册这三个基本的过程。我们以ApplicationContext为例讲解,ApplicationContext系列容器也许是我们最熟悉的,因为web项目中使用的XmlWebApplicationContext就属于这个继承体系,还有ClasspathXmlApplicationContext等,其继承体系如下图所示:
ApplicationContext允许上下文嵌套,通过保持父上下文可以维持一个上下文体系。对于bean的查找可以在这个上下文体系中发生,首先检查当前上下文,其次是父上下文,逐级向上,这样为不同的Spring应用提供了一个共享的bean定义环境。
从ApplicationContext接口的实现,我们看出其特点:
1. 支持信息源,可以实现国际化。(实现MessageSource接口)
2. 访问资源。(实现ResourcePatternResolver接口,这个后面要讲)
3. 支持应用事件。(实现ApplicationEventPublisher接口)
我们看ClassPathXmlApplicationContext是如何建立IOC容器,先看其构造函数:
- public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
- throws BeansException {
- super(parent);
- setConfigLocations(configLocations);
- if (refresh) {
- refresh();
- }
- }
refresh的模板是在AbstractApplicationContext中:
- 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();
- }
- ……
这里是我们分析的入口,其完成了整个的bean初始化过程。
spring IOC源码分析(1)的更多相关文章
- Spring IOC 源码分析
Spring 最重要的概念是 IOC 和 AOP,本篇文章其实就是要带领大家来分析下 Spring 的 IOC 容器.既然大家平时都要用到 Spring,怎么可以不好好了解 Spring 呢?阅读本文 ...
- spring IoC源码分析 (3)Resource解析
引自 spring IoC源码分析 (3)Resource解析 定义好了Resource之后,看到XmlFactoryBean的构造函数 public XmlBeanFactory(Resource ...
- Spring IoC 源码分析 (基于注解) 之 包扫描
在上篇文章Spring IoC 源码分析 (基于注解) 一我们分析到,我们通过AnnotationConfigApplicationContext类传入一个包路径启动Spring之后,会首先初始化包扫 ...
- Spring Ioc源码分析系列--Ioc的基础知识准备
Spring Ioc源码分析系列--Ioc的基础知识准备 本系列文章代码基于Spring Framework 5.2.x Ioc的概念 在Spring里,Ioc的定义为The IoC Containe ...
- Spring Ioc源码分析系列--前言
Spring Ioc源码分析系列--前言 为什么要写这个系列文章 首先这是我个人很久之前的一个计划,拖了很久没有实施,现在算是填坑了.其次,作为一个Java开发者,Spring是绕不开的课题.在Spr ...
- Spring Ioc源码分析系列--Ioc源码入口分析
Spring Ioc源码分析系列--Ioc源码入口分析 本系列文章代码基于Spring Framework 5.2.x 前言 上一篇文章Spring Ioc源码分析系列--Ioc的基础知识准备介绍了I ...
- Spring Ioc源码分析系列--Ioc容器BeanFactoryPostProcessor后置处理器分析
Spring Ioc源码分析系列--Ioc容器BeanFactoryPostProcessor后置处理器分析 前言 上一篇文章Spring Ioc源码分析系列--Ioc源码入口分析已经介绍到Ioc容器 ...
- Spring Ioc源码分析系列--Ioc容器注册BeanPostProcessor后置处理器以及事件消息处理
Spring Ioc源码分析系列--Ioc容器注册BeanPostProcessor后置处理器以及事件消息处理 前言 上一篇分析了BeanFactoryPostProcessor的作用,那么这一篇继续 ...
- Spring Ioc源码分析系列--Bean实例化过程(一)
Spring Ioc源码分析系列--Bean实例化过程(一) 前言 上一篇文章Spring Ioc源码分析系列--Ioc容器注册BeanPostProcessor后置处理器以及事件消息处理已经完成了对 ...
- Spring Ioc源码分析系列--Bean实例化过程(二)
Spring Ioc源码分析系列--Bean实例化过程(二) 前言 上篇文章Spring Ioc源码分析系列--Bean实例化过程(一)简单分析了getBean()方法,还记得分析了什么吗?不记得了才 ...
随机推荐
- 纯CSS气泡框实现方法探究
气泡框(或者提示框)是网页中一种很常见的元素,大多用来展示提示信息,如下图所示: 拆分来看,形如这种气泡框无外乎就是一个矩形框+一个指示方向的三角形小箭头,要制作出这样的气泡框,如果解决了三角形小箭头 ...
- 编程规范 html部分
不管有多少人共同参与同一项目,一定要确保每一行代码都像是同一个人编写的. HTML 部分 语法 对于属性的定义,确保全部使用双引号,绝不要使用单引号. 为每个 HTML 页面的第一行添加标准模式(st ...
- JPA 批量新增
1. 在实现类 增加 EntityManager 注入 private EntityManager em; @PersistenceContext(name = "EntityManager ...
- JavaScript的检测属性、属性特性、枚举属性
/* 检测属性 检测属性可以通过三种方式 1.通过in运算符 2.通过hasOwnPerperty() 如果给定的属性是继承属性将返回false 3.通过propertyIsEnumerable(): ...
- javac 不是内部或外部命令
安装好JDK后 用 java 命令测试OK! 用 java -version 命令测试OK! 用 javac ...
- ASP.NET MVC5 入门
参考资料<ASP.NET MVC5 高级编程>第5版 第1章 入门 1.1 ASP.NET MVC 简介 ASP.NET MVC是一种构建Web 应用程序的框架,它将一般的MVC(Mode ...
- c语言学习的第6天
#include <stdio.h> int main() { int x=100; if(x==0) { printf("x等于0\n"); printf(" ...
- 关于js一般对象与标配对象
当一个js函数对象被创建时,Function 构造器产生的函数对象会运行类似这样的一些代码 this.prototype={constructor:this} 新函数被赋予了一个prototype属性 ...
- 透过c的编程原则,来规范自己现在的一些编程习惯
1.合理的使用注释 注释为:/*…………*/ 注释有以下几种情况: 1) 版本.版权声明. 2) 函数接口说明. 3) 重要的代码或者段落显示. 注释注意: 1) 注释是对代码的解释,不是对文档.注释 ...
- CKeditor的简单使用
由于项目中要使用ckeditor 做个推荐功能,由于值设定到文本内容,就选择最基本的使用. 使用的版本为当前最新版本4.4.7,你需要下载两部分,一个是前台使用,一个是后台使用, 你可以到我的网盘中下 ...