在之前我们说过,Spring的IOC容器是一个提供IOC支持的轻量级容器,除了基本的IOC支持,它作为轻量级容器还提供了IOC之外的支持。如在spring的IOC容器之上,Spring还提供了AOP服务的支持
在spring中容器的实现有两种类型:BeanFactory和ApplicationContext
BeanFactory是最基本的容器实现,提供完整的ioc服务支持,默认采用懒加载的方式,所以容器的初始化速度很快
ApplicationContext则是基于BeanFactory进行封装后的结果,BeanFactory所拥有的功能ApplicationContext都会拥有,同时ApplicationContext还具备一些高级功能:事件发布,国际消息化处理等
本章我们将主要讲述BeanFactory的功能
BeanFactory既然是ioc容器的具象化,那么它的主要作用肯定是对bean进行管理,那么想要交给BeanFactory去管理肯定得提供一些信息标记哪些类需要其去管理,之前说明ioc的时候已经说过了是采用了三种方式来告诉ioc进行处理的分别是硬编码,外部信息和注解的方式。
注入方式 | 代表实现 | 信息源特性 | 核心组件 |
---|---|---|---|
外部信息注入 | XML 配置文件 | 外部化配置(文件/资源) | XmlBeanDefinitionReader |
注解注入 | 组件扫描(@Component ) | 代码内嵌元数据(注解) | ClassPathBeanDefinitionScanner |
硬编码注入 | Java 配置类(@Bean ) | 编程式 Java 代码 | AnnotatedBeanDefinitionReader |
这些组件其中一个比较重要的就是BeanDefinitionReader,几乎所有的注入方式最终的本质都是通过这个BeanDefinitionReader这个接口注入的,这个接口有多种实现类分别用来读取不同类型的注入方式。那么当将这些bean信息读入之后则会将他们封装为BeanDefinition类对象,用来表示这些bean的信息。
同时这些BeanDefinition并不是直接就存放到BeanFactory当中的而是存放到BeanFactory内的BeanDefinitionRegistry。我们知道BeanFactory是采用懒加载的方式,当读取到所有的bean信息之后只是将其存放到BeanDefinitionRegistry当中而不会去创建bean对象,只有真正需要的时候BeanFactory则会去从BeanDefinitionRegistry读取到BeanDefinition根据BeanDefinition信息去创建bean对象
那么聊到bean的注入,我们需要知道bean的scope有几种。什么是scope?scope说明的是对象应该所处的场景和事件,即bean在进入相应scope之前创建,当bean不在相应的scope的时候就销毁。
spring最初提供了两种scope分别是singleton和prototype。但发布2.0之后又引入了另外三种scope分别是request,session和global session
singleton:
在spring中singleton这个scope则代表着在ioc容器内只有一个实例对象,所有该对象的引用共享一个实例,而他的寿命则是几乎与ioc容器寿命相当。
同时需要注意的是,当ioc容器关闭的时候会卸载所有的bean,这里的卸载指的是将这些对象的引用从ioc容器中剔除,而剔除之后该对象没有引用则会被jvm进行回收。因此这里的卸载并不是说像jvm一样将数据进行回收
spring容器中只有一个实例对象,并且生命周期几乎与容器生命周期相同
prototype:
在spring中prototype则是与singleton相反,他在容器内则是可以出现多个实例对象,每当需要他的时候容器就会产生一个对象。但是需要注意的是容器产生该对象之后spring容器就会放弃对该bean的管理。
也就是说对于prototype类型的bean只要生成之后就会交给程序员自己去管理它,spring容器会直接解除该对象的引用关系。交给对象自生自灭
request,session和global session
这三个scope是属于spring2.0之后添加的,他并不像前面两个通用性强,这些只适用于web应用程序
request:表示在一个请求的区域内对象存活,当请求结束后,对象的生命周期将会结束。每当一个request请求到来的时候都会创建一个对象
session:表示在一个会话中存活,与request相比可能存活时间更长一些其他方面则是没有什么差别
global session只有应用基于portlet的web应用程序中才有意义,他映射portlet的global范围的session。如果在普通的基于servlet的web中使用了这个scope只会当做普通的session对待
scope讲完了,我们知道加载bean都是交给BeanFactory去实例化的,那么如果我们要自定义方式来实例化bean对象要怎么办呢?spring则是提供了FactoryBean这个类用来自定义实现bean的实例化
FactoryBean是Spring容器提供的一种可以扩展容器对象实例化逻辑的接口,主语是bean,也就是说,它本身与其他注册到容器的bean对象一样只是一个bean而已,只不过这个类型的bean本身的作用就是生成对象的工厂(factory)
FactoryBean只定义了三种方法:
getObject表示返回该工厂生产的实例对象,getObjectType方法仅返回getObject返回的对象类型,如果预先无法确定则会返回null。isSingleton则是返回对象是否为单例
spring在很多地方都使用了FactoryBean,下面是几个例子。