Spring源码学习(一):IOC容器初始化

时间:2022-01-17 05:10:52

Spring中,最基本的IOC容器为BeanFactory。

这是容器对bean的基本管理接口

1. public interface BeanFactory {   
2.
3. //这里是对FactoryBean的转义定义,因为如果使用bean的名字检索FactoryBean得到的对象是工厂生成的对象,
4. //如果需要得到工厂本身,需要转义
5. String FACTORY_BEAN_PREFIX = "&";
6.
7. //这里根据bean的名字,在IOC容器中得到bean实例,这个IOC容器就是一个大的抽象工厂。
8. Object getBean(String name) throws BeansException;
9.
10. //这里根据bean的名字和Class类型来得到bean实例,和上面的方法不同在于它会抛出异常:如果根据名字取得的bean实例的Class类型和需要的不同的话。
11. Object getBean(String name, Class requiredType) throws BeansException;
12.
13. //这里提供对bean的查找
14. boolean containsBean(String name);
15.
16. //这里根据bean名字得到bean实例,并同时判断这个bean是不是单件
17. boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
18.
22. //这里得到bean的别名,如果根据别名检索,那么其原名也会被检索出来
23. String[] getAliases(String name);
24.
25. }

基本操作

ClassPathResource res = new ClassPathResource("beans.xml");  //资源定位
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();//工场 BeanFactory
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory); //配置Reader
reader.loadBeanDefinitions(res); //加载

在BeanFactory的基础上又扩展出了ApplicationContext。
ApplicationContext的优点:

  1. 可以支持不同的信息源,ApplicationContext扩展了MessageSource
  2. 访问资源
  3. 支持应用事件,继承了接口ApplicationEventPublisher

AppicationContext的具体实现:FileSystemXmlApplicationContext和 ClassPathXmlApplicationContext,一个基于文件系统,一个基于类路径上的查找。

    public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)   
throws BeansException {
super(parent);
this.configLocations = configLocations;
if (refresh) {
 //这里是IoC容器的初始化过程,其初始化过程的大致步骤由AbstractApplicationContext来定义
refresh();
}
...
}


public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
synchronized (this.activeMonitor) {
this.active = true;
}

// 完成资源位置定义,bean载入和向IOC容器注册的过程
refreshBeanFactory();
…………
}

使用XmlBeanDefinitionReader来读取资源。不断的调用loadBeanDefinitons方法,将资源定位。Spring中提供了各种资源的抽象。然后进行bean的加载,是通过将资源转换成Document结构(DOM对象)。然后解析XML中每个子节点,解析好后放入BeanDefinition里。

BeanDefinition是bean信息的主要载体,是IOC容器的管理对象。

最后注册bean。把bean名字和bean定义放入一个HashMap中进行维护。

Beanfactory 和Factory bean,其中BeanFactory指的是IOC容器的编程抽象,比如ApplicationContext, XmlBeanFactory等,这些都是IOC容器的具体表现。而 FactoryBean只是一个可以在IOC容器中被管理的一个bean,是对各种处理过程和资源使用的抽象,Factory bean在需要时产生另一个对象,而不返回FactoryBean本身,我们可以把它看成是一个抽象工厂,对它的调用返回的是工厂生产的产品。所有的 Factory bean都实现特殊的org.springframework.beans.factory.FactoryBean接口,当使用容器中factory bean的时候,该容器不会返回factory bean本身,而是返回其生成的对象。

最后再总结一下IOC容器初始化过程。通过refresh方法来进行启动,通过不断的loadbeandefinition来加载bean,将资源定位后,使用BeanDefinitionReader完成定义信息的解析和bean信息的注册。将获取的bean信息放入BeanDefiniton对象中,然后将它在IOC容器中注册(通过HashMap,来维护beanName和BeanDefinition)。

Web应用中作用域

singleton:单例模式,在整个Spring IoC容器中,使用singleton定义的Bean将只有一个实例

prototype:原型模式,每次通过容器的getBean方法获取prototype定义的Bean时,都将产生一个新的Bean实例

request:对于每次HTTP请求,使用request定义的Bean都将产生一个新实例,即每次HTTP请求将会产生不同的Bean实例。只有在Web应用中使用Spring时,该作用域才有效

session:对于每次HTTP Session,使用session定义的Bean豆浆产生一个新实例。同样只有在Web应用中使用Spring时,该作用域才有效

globalsession:每个全局的HTTP Session,使用session定义的Bean都将产生一个新实例。典型情况下,仅在使用portlet context的时候有效。同样只有在Web应用中使用Spring时,该作用域才有效