- Spring IOC容器概述
IoC不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合、更优良的程序。传统应用程序都是由我们在类内部主动创建依赖对象,从而导致类与类之间高耦合,难于测试;有了IoC容器后,把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是松散耦合,这样也方便测试,利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。
其实IoC对编程带来的最大改变不是从代码上,而是从思想上,发生了“主从换位”的变化。应用程序原本是老大,要获取什么资源都是主动出击,但是在IoC/DI思想中,应用程序就变成被动的了,被动的等待IoC容器来创建并注入它所需要的资源了 。
●谁依赖于谁:当然是应用程序依赖于IoC容器;
●为什么需要依赖:应用程序需要IoC容器来提供对象需要的外部资源;
●谁注入谁:很明显是IoC容器注入应用程序某个对象,应用程序依赖的对象;
●注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)。 - Ioc容器的BeanFactory和ApplicationContext
spring容器主要分为两大类:1.实现BeanFactory接口的简单容器系列,只是实现容器的最基本功能。2.ApplicationContext应用上下文,作为容器的高级形态存在。
BeanFactory类结构体系:
BeanFactory接口及其子类定义了spring IoC容器体系结构,由于BeanFactory体系非常的庞大和复杂,因此要理解Spring IoC,需要先理清BeanFactory的继承机构。
ApplicationContext的结构体系:
ApplicationContext接口是一个BeanFactory基础上封装了更多功能的,Spring中最为常用的IoC容器,其包含两个子接口:ConfigurableApplicationContext、WebApplicationContext。
BeanFactory:
BeanFactory接口定义了Spring IoC容器的基本功能规范,是Spring IoC容器所应遵守的最底层和最基本的编程规范。BeanFactory接口中所定义的IoC容器的主要方法如下:
(1).Object getBean(Stringname) throws BeansException;
getBean是IoC容器中最重要的方法,通过该方法可以取得IoC容器中管理的Bean,Bean的取得是通过指定名字来进行所引的。
(2). T getBean(String name, Class requiredType) throws BeansException;
根据指定的名字和类型取得IoC容器中管理的Bean,和getBean(String name)方法类似,只是多提供了一个类型安全验证机制。
(3). T getBean(Class requiredType) throws BeansException;
根据指定的类型取得IoC容器中管理的Bean,该方法根据指定的类型调用ListableBeanFactory(BeanFactory下的)中的取得Bean方法,但是也可能根据给定的类型调用通过名字取得Bean的方法。
(4). Object getBean(String name, Object… args) throws BeansException;
该方法重载了getBean(String name)方法,可变参数主要用来指定是否显示使用静态工厂方法创建一个原型(prototype)Bean。
(5). boolean containsBean(String name);
该方法让用户判断IoC容器中是否含有指定名字的Bean。
(6). boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
该方法用来查询指定名字的Bean是否是单态类型(singleton)的Bean。
(7). boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
该方法用来查询指定名字的Bean是否是原型(prototype)类型的Bean。
(8). boolean isTypeMatch(String name, Class targetType)throws NoSuchBeanDefinitionException;
该方法用来查询指定名字的Bean的class类型是否支持特定的class类型。
(9). Class
public interface ApplicationContext extends ListableBeanFactory, HierarchicalBeanFactory,
MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
//获取ApplicationContext的id
String getId();
//获取ApplicationContext的displayName
String getDisplayName();
//获取ApplicationContext第一次加载的时间戳
long getStartupDate();
//获取ApplicationContext容器的父容器
ApplicationContext getParent();
//获取自动装配功能的BeanFactory
AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;
}
ApplicationContext的特性:
ApplicationContext是Spring提供的一个高级的IoC容器,它除了能够提供IoC容器的基本功能外,还为用户提供了以下的附加服务:
a.支持不同的信息源:
ApplicationContext扩展了MessageSource接口,可以支持国际化的实现。
b.访问资源:
ApplicationContext继承了DefaultResourceLoader的子类,通过ResourceLoader和Resource的支持,ApplicationContext可以加载不同地方的Bean定义资源文件,尤其可以从不同IO途径获取Bean定义信息。可以使用户程序灵活地定义Bean定义信息。
c.支持应用事件:
ApplicationContext继承了ApplicationEventPublisher接口,在程序上下文中引入了事件机制,这些事件和Bean生命周期的结合为Bean的过来提供了便利。
- Ioc容器的初始化过程
spring的IoC容器初始化包括:Bean定义资源文件的定位、载入和注册3个基本过程。
(1).Bean定义资源文件的定位:
Bean定义资源文件定位由ResourceLoader通过统一的Resource接口来完成,Resource接口将各种形式的Bean定义资源文件封装成统一的、IoC容器可进行载入操作的对象。
(2).Bean定义资源文件的载入:
Bean定义资源文件载入的过程是将Bean定义资源文件中配置的Bean转换成IoC容器中所管理Bean的数据结构形式。SpringIoC中管理的Bean的数据结构是BeanDefinition,BeanDefinition是POJO对象在IoC容器中的抽象。
(3).Bean定义的注册:
通过调用BeanDefinitionRegistry接口把从Bean定义资源文件中解析的Bean向IoC容器进行注册,在IoC容器内部,是通过一个HashMap来存储这些Bean对象数据的。 - Ioc容器的依赖注入
依赖注入的过程是用户第一次向ioc容器索要bean时触发的,也有例外就是Wien在beanDefinition信息中通过控制lazy-init属性来让容器完成对bean的预实例化。
用户使用getBean方法向Spring IoC容器索取被管理的Bean:我们查看BeanFactory的getBean方法实现,发现有3个类实现了该方法:SimpleJndiBeanFactory,StaticListableBeanFactory和AbstractApplicationContext。我们以AbstractApplicationContext为例,分析其向容器索取的处理过程。
AbstractApplicationContext中getBean相关方法的源码如下:
我们查看BeanFactory的getBean方法实现,发现有3个类实现了该方法:SimpleJndiBeanFactory,StaticListableBeanFactory和AbstractApplicationContext。我们以AbstractApplicationContext为例,分析其向容器索取的处理过程。
AbstractApplicationContext中getBean相关方法的源码如下:
(1).对于集合类型的属性,将其属性值解析为目标类型的集合后直接赋值给属性。
(2).对于非集合类型的属性,大量使用了JDK的反射和内省机制,通过属性的getter方法(reader method)获取指定属性注入以前的值,同时调用属性的setter方法(writer method)为属性设置注入后的值。