一、BeanDefinition
BeanDefinition是配置文件<bean>元素标签在容器中内部表示形式。创建最终的BeanDefinition主要包括两个步骤:
1)利用BeanDefinitionReader对配置信息Resource进行读取,通过XML解析器解析配置信息的DOM对象,简单地为每个<bean>生成对应的BeanDefinition对象。但是这里生成的BeanDefinition可能是半成品,因为在配置文件中,我们可能通过占位符变量引用外部属性文件的属性,这些占位符变量在这一步还没有被解析出来。
2)利用容器中注册的BeanFactoryPostProcessor对半成品的BeanDefinition进行加工处理,将以占位符表示的配置解析为最终的实际值,这样半成品的BeanDefinition就为成品的。
二、FactoryBean和BeanFactory
一个是Factory,也就是IoC容器或对象工厂;一个是Bean。在Spring中,所有Bean都是由BeanFactory(也就是IoC容器)来进行管理的。但对FactoryBean而言,这个Bean不是简单的Bean,而是一个能产生或者修饰对象生成的工厂Bean,它的实现与设计模式中的工厂模式和修饰器模式类似。BeanFactory接口设计了getBean方法,这个方法是使用IoC容器API的主要方法,Bean的取得是通过指定名字来进行索引的。
BeanFactory继承体系:http://mydream1987.iteye.com/blog/1151380
AutowireCapableBeanFactory→AbstractAutowireCapableBeanFactory→DefaultListableBeanFactory→XmlBeanFactory IoC容器的实现系列。XmlBeanFactory这个IoC容器可以读取以XML形式定义的BeanDefinition。
@Deprecated public class XmlBeanFactory extends DefaultListableBeanFactory { private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this); /** * Create a new XmlBeanFactory with the given resource, * which must be parsable using DOM. * @param resource XML resource to load bean definitions from * @throws BeansException in case of loading or parsing errors */ public XmlBeanFactory(Resource resource) throws BeansException { this(resource, null); } /** * Create a new XmlBeanFactory with the given input stream, * which must be parsable using DOM. * @param resource XML resource to load bean definitions from * @param parentBeanFactory parent bean factory * @throws BeansException in case of loading or parsing errors */ public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException { super(parentBeanFactory); this.reader.loadBeanDefinitions(resource); } }
编程式使用IOC容器:
ClassPathResource res = new ClassPathResource("beans.xml"); DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory); reader.loadBeanDefinitions(res);
三、IOC容器初始化
IoC容器的初始化包括BeanDefinition的Resouce定位、载入和注册这三个基本的过程。Spring容器的初始化主要分为三个步骤,分别使Bean信息的定位,解析与注册。以XML文件形式的Bean信息为例,Spring首先找到XML文 件的位置,然后读取此文件,并且将文件解析成相应的BeanDefinition,最后将获取到的BeanDefinition注册到BeanFactory中去。
从这副顺序图中我们可以看出,Spring容器的初始化过程主要由四个类来完成,我们可以参考下类的注释以了解这几个类的职责:
- XmlBeanDefinitionReader:用于XML Bean定义信息的BeanDefinitionReader,将事实上的XML文件读取代理给BeanDefinitionDocumentReader接口的一个实现。
- BeanDefinitionDocumentReader:用于解析Spring Bean定义信息的服务提供接口(SPI),在实际解析DOM文档的时候,由XmlBeanDefinitionReader来调用。
- BeanDefinitionParserDelegate:用于解析XML Bean定义信息的有状态代理类。负责一个Bean的定义信息解析策划能够BeanDefinition对象。
- BeanDefinitionRegistry:负责将得到的Bean定义信息注册到BeanFactory中。
四、Spring IOC实现
我们需要从总体概念上对spring IOC有一个全局认识:
五、总述
IOC-Inversion of Control,中文意为控制反转,将bean之内相互耦合的依赖关系交给框架来处理,bean的内部不需要再维护其所依赖bean的生命周期而更加关注自身的业务逻辑。spring IOC作为IOC的一种实现,不仅管理了各个bean的生命周期和依赖关系,还提供了丰富的扩展接口去动态的修改bean的行为。
bean的生命周期:从bean的创建、初始化、使用再到最终被销毁,整个过程中bean对象由框架来统一管理(除了prototype的bean在创建初始化后脱离了容器管理,由应用使用方自己来负责bean的销毁回收)。
bean的作用域:按照bean的作用范围,bean的作用域分为以下5种:singleton、prototype、request、session、global session。
singleton为单例bean的作用域,在容器中被创建后仅维持一份bean对象,创建后被缓存,任何请求该bean对象都是在这一个bean上进行操作,所以要注意线程安全问题,防止并发带来的数据修改不一致问题。比如DAO层的某个bean会被多个service使用,这些bean可以由同一个对象来代替,因为bean的数据源和行为都是一致的。
prototype为原型bean的作用域,在任何被注入和容器中执行beanFactory.getBean()的时候,容器都会为此类bean创建一个全新的对象供其他对象使用。由于不同对象中的bean是完全不同的实例,所以它们之间互不影响,但是这样一来系统开销会比较大。
在spring 2.0之前仅有单例和非单例两种类型的bean作用域,到了2.0之后引入了request、http session和global session这三种作用域。
request是针对web应用的http请求级别的bean作用域。HttpRequest就是一个很好的例子,request请求中包含用户每次请求中的数据,每一次请求中传输的数据是不同的。
http session是指bean生命周期贯穿一次完整的http会话过程。只要客户端和web服务器之间的会话没有断开,session级别的bean对象就不会被销毁。具体例子如HttpSession对象,不同的session容器会为其创建不同的session对象。
六、