《partner4java 讲述Spring源码》之第一步:Spring IoC
(导读:《partner4java 讲述Spring源码》仅为辅助学习,关键是我是一个“菜鸟”,希望老鸟们还是自己去研究源码比较妥当)
SpringIoC容器概述
IoC容器和依赖反转模式:
早在2004年,Martin Fowler就提出了“哪些方面的控制被反转了?”这个问题。他总结出是依赖对象的获得被反转了。基于这个结论,他为控制反转创造了一个更好的名字:依赖注入。许多非凡的应用(比HelloWorld.java更加优美,更加复杂)都是由两个或是更多的类通过彼此的合作来实现业务逻辑,这使得每个对象都需要,与其合作的对象(也就是它所依赖的对象)的引用。如果这个获取过程要靠自身实现,那么如你所见,这将导致代码高度耦合并且难以测试。
关于如何反转对依赖的控制,把控制权从具体业务对象手中转交到平台或者框架中,是降低面向对象系统设计复杂性和提高面向对象系统可测试性的一个有效的解决方案。
它促进了IoC设计模式的发展,是IoC容器要解决的核心问题。同时,也是产品化的IoC容器出现的推动力。
Spring IoC的应用场景:
在Spring中,Spring IoC提供了一个基本的JavaBean容器,通过IoC模式管理依赖关系,并通过依赖注入和AOP切面编程增强了为JavaBean这样的POJO对象赋予事务管理、生命周期管理等基本功能;
而对于EJB,一个简单的EJB组件需要编写远程/本地接口、Home接口以及Bean的实现类,而EJB运行是不能脱离EJB容器的,查找其他的EJB组件也需要诸如JNDI这样的方式,从而造成了对EJB容器和技术规范的 依赖。
IoC容器系列的设计和实现:BeanFactory和ApplicationContext
两个主要的容器系列:
BeanFactory接口的实现,这个系列仅实现了容器的基本功能;The root interface for accessing a Spring bean container. This is the basic client view of a bean container;
ApplicationContext应用上下文,他作为容器的高级形态而存在。应用上线问在简单容器的基础上,增加了许多面向框架的特性,同时对应用环境做了许多适配。(此接口父接口HierarchicalBeanFactory也继承自BeanFactory)Central interface to provide configuration for an application. This is read-only while the application is running, but may be reloaded if the implementation supports this.
Spring的IoC容器系列:把IoC容器比喻成水桶,水桶有大小,作用也不同。
BeanDefinition:来管理基于Spring的应用中的各种对象以及他们之间的相互依赖关系,抽象了我们对Bean的定义,是让容器起作用的主要数据类型。A BeanDefinition describes a bean instance, which has property values, constructor argument values, and further information supplied by concrete implementations.
在计算机世界里,所有的功能都是建立在通过数据对现实进行抽象的基础上的。IoC容器是用来管理对象依赖关系的,对IoC容器来说,BeanDefinition就是对依赖反转模式中管理的对象依赖关系的数据抽象,也是容器实现依赖反转功能的核心数据结构,依赖反转功能都是围绕对这个BeanDefinition的处理来完成。
了解BeanFactory和ApplicationContext之间的区别对我们理解和使用IoC容器也是比较重要的。弄清楚这两种重要容器的之间的区别和联系,便于我们最佳的扩展。
Spring IoC容器设计:
BeanFactory:接口定义了基本的IoC容器的规范。基本定义了获取bean和获取判断bean全局范围类型等。
BeanFactory主要实现类 -- DefaultListableBeanFactory。
如BeanFactory基本结构图.png。
ApplicationContext:应用上下文接口为核心的接口设计。
如IoC基本结构图.png
1、BeanFactory的应用场景
BeanFactory接口定义了IoC容器最基本的形式,并且提供了IoC容器所应该遵守的最基本的服务定义。
用户使用容器时,可以使用转义符"&"来得到FactoryBean本身,而不是FactoryBean产生出来的对象。
核心的getBean方法,又提供了一些对bean的判断等,bean数据都在BeanDefinition中定义。
(他的实现与设计模式中的工厂模式和修饰器模式类似)
通过BeanFactory接口方法中的getBean来使用Bean的名字,从而在获取Bean时,如果是获取prototype类型,还可以指定构造函数的对应参数。
2、BeanFactory容器的设计原理
在Spring中,DefaultListableBeanFactory作为一个默认的功能完整的IoC容器来使用的。
例子:XmlBeanFactory建立在DefaultListableBeanFactory基础上(ApplicationContext中也用到了他)。XmlBeanFactory利用XmlBeanDefinitionReader,通过方法loadBeanDefinitions(resource)读取以XML方法定义的BeanDefinition的IoC容器。通过Spring中的Resource I/O操作类,来获取XML形式定义的BeanDefinition。
第三步:BeanDefinition在IoC容器中的注册
通过载入和解析后得到BeanDefinitionHolder,我们需要注册进默认容器DefaultListableBeanFactory,容器中定义了Map用于存放注册的BeanDefinition。
注册过程辗转反侧又回到了DefaultListableBeanFactory里: