Spring源码分析之IoC容器初始化
本文首发于cdream个人博客(点击获得更加阅读体验)
欢迎转载,转载请注明出处
作为一个java程序员,保守估计一年里也都有300天要和Spring有亲密接触~~像我这种怕是每天都要撸撸Spring,所以这次也要做个深入了解!这次就来看看Spring是怎么初始化IoC容器的😄
我们都是知道Spring为企业级应用提供了丰富的功能,而这些功能底层都依赖于底层最核心的两种特性IOC和AOP。
IOC实现里主要包括两部分,一个是IOC容器初始化,另外一个是依赖注入,由于两部分是相对独立的部分,所以分成不同文章讲解,本篇主要讲述IOC容器的初始化。
一、IoC的概念
控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体,将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。
上面这个概念是来自维基百科,在Expert Spring MVC and Web Flow和Expert One-on-One J2EE without EJB等书中都也是将依赖注入看作是IoC的一种方式。不过有些地方会把IoC和DI看成一个概念(例如Spring in Action、Spring揭密等书),不过没关系,不影响我们理解就可以。
A类的正常的运行需要B类
没有IoC之前我们在使用A类的某个方法时,总会依赖于B类的一些功能,这样我们就要去new个B对象,有时还要考虑什么时候销毁,什么时候使用单例模式等等,类少了还好管理,这要是多起来真是再聪明的人怕也是要十个头九个大了, 而且A、B之间的依赖关系使各代码紧密耦合,一旦B类的出现问题,或者某天干脆不用B了用C,那是不是A类里的new B()全得换成new C()?想象都觉得累...
有了IoC之后,对象创建都交给第三方容器处理,A中的B通过注入来完成,B出问题了,或者需要换成C了,只要把注入的B换成C就可以(现实开发中B、C可以实现相同的接口解决~所以啊,Spring是面向接口编程鸭)。
- Expert One-on-One J2EE without EJB这本书是spring爸爸Rod Johnson写的,进入Spring的BeanFactory类里面看看作者就是他,哈哈!
public interface ApplicationContext extends EnvironmentCapable,ListableBeanFactory,HierarchicalBeanFactory,MessageSource,ApplicationEventPublisher,ResourcePatternResolver { /** * 返回该上下文的id(unique) */ String getId(); /** * 返回上下文所属应用的名字 */ String getApplicationName(); /** * 返回这个上下文友好的名字 */ String getDisplayName(); /** * 返回上下文首次加载的时间 */ long getStartupDate(); /** * 返回父类上下文 */ ApplicationContext getParent(); /** * 功能性的暴露自动装配的工厂,并不常用 */ AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException; }
这里面的方法也不多,主要的方法都在继承的接口里
BeanDifinition:储存 Spring中 Bean的信息,包括各属性名,类名,是否单例等,抽象了我们对 Bean的定义,是让容器起作用的主要数据类型。对 IOC 容器来说,BeanDefinition 就是对控制反转模式中管理的对象依赖关系的数据抽象。
接下来正式进入IoC容器初始化的分析,以FileSystemXmlApplicationContext为例,下面是FileSystemXmlApplicationContext的继承关系~(这形状,满满的爱啊,哈哈)
BeanDefinition的Resource定位
public class FileSystemXmlApplicationContext extends AbstractXmlApplicationContext { /** * 无参构造 */ public FileSystemXmlApplicationContext() { } /** * 传入父类上下文 */ public FileSystemXmlApplicationContext(ApplicationContext parent) { super(parent); }