Spring框架学习[IoC容器高级特性](一)

2014-11-24 03:11:10 · 作者: · 浏览: 8

1.通过前面4篇文章对Spring IoC容器的源码分析,我们已经基本上了解了Spring IoC容器对Bean定义资源的定位、读入和解析过程,同时也清楚了当用户通过getBean方法向IoC容器获取被管理的Bean时,IoC容器对Bean进行的初始化和依赖注入过程,这些是Spring IoC容器的基本功能特性。Spring IoC容器还有一些高级特性,如使用lazy-init属性对Bean预初始化、FactoryBean产生或者修饰Bean对象的生成、IoC容器初始化Bean过程中使用BeanPostProcessor后置处理器对Bean声明周期事件管理和IoC容器的autowiring自动装配功能等。

2.Spring IoC容器的lazy-init属性实现预实例化:

通过前面我们对IoC容器的实现和工作原理分析,我们知道IoC容器的初始化过程就是对Bean定义资源的定位、载入和注册,此时容器对Bean的依赖注入并没有发生,依赖注入主要是在应用程序第一次向容器索取Bean时,通过getBean方法的调用完成。

当Bean定义资源的 元素中配置了lazy-init属性时,容器将会在初始化的时候对所配置的Bean进行预实例化,Bean的依赖注入在容器初始化的时候就已经完成。这样,当应用程序第一次向容器索取被管理的Bean时,就不用再初始化和对Bean进行依赖注入了,直接从容器中获取已经完成依赖注入的现成Bean,可以提高应用第一次向容器获取Bean的性能。

下面我们通过代码分析容器预实例化的实现过程:

(1).先从IoC容器的初始会过程开始,通过前面文章分析,我们知道IoC容器读入已经定位的Bean定义资源是从refresh方法开始的,我们首先从AbstractApplicationContext类的refresh方法入手分析,源码如下:

[java]
  1. //容器初始化的过程,读入Bean定义资源,并解析注册 public void refresh() throws BeansException, IllegalStateException {
  2. synchronized (this.startupShutdownMonitor) { //调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识
  3. prepareRefresh(); //告诉子类启动refreshBeanFactory()方法,Bean定义资源文件的载入从
  4. //子类的refreshBeanFactory()方法启动 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
  5. //为BeanFactory配置容器特性,例如类加载器、事件处理器等 prepareBeanFactory(beanFactory);
  6. try { //为容器的某些子类指定特殊的BeanPost事件处理器
  7. postProcessBeanFactory(beanFactory); //调用所有注册的BeanFactoryPostProcessor的Bean
  8. invokeBeanFactoryPostProcessors(beanFactory); //为BeanFactory注册BeanPost事件处理器.
  9. //BeanPostProcessor是Bean后置处理器,用于监听容器触发的事件 registerBeanPostProcessors(beanFactory);
  10. //初始化信息源,和国际化相关. initMessageSource();
  11. //初始化容器事件传播器. initApplicationEventMulticaster();
  12. //调用子类的某些特殊Bean初始化方法 onRefresh();
  13. //为事件传播器注册事件监听器. registerListeners();
  14. //这里是对容器lazy-init属性进行处理的入口方法 finishBeanFactoryInitialization(beanFactory);
  15. //初始化容器的生命周期事件处理器,并发布容器的生命周期事件 finishRefresh();
  16. } catch (BeansException ex) {
  17. //销毁以创建的单态Bean destroyBeans();
  18. //取消refresh操作,重置容器的同步标识. cancelRefresh(ex);
  19. throw ex; }
  20. } }

    在refresh方法中ConfigurableListableBeanFactorybeanFactory = obtainFreshBeanFactory();启动了Bean定义资源的载入、注册过程,而finishBeanFactoryInitialization方法是对注册后的Bean定义中的预实例化(lazy-init=false,Spring默认就是预实例化,即为true)的Bean进行处理的地方。

    (2).finishBeanFactoryInitialization处理预实例化Bean:

    当Bean定义资源被载入IoC容器之后,容器将Bean定义资源解析为容器内部的数据结构BeanDefinition注册到容器中,AbstractApplicationContext类中的finishBeanFactoryInitialization方法对配置了预实例化属性的Bean进行预初始化过程,源码如下:

    [java]
    1. //对配置了lazy-init属性的Bean进行预实例化处理 protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    2. //这是Spring3以后新加的代码,为容器指定一个转换服务(ConversionService) //在对某些Bean属性进行转换时使用
    3. if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) && beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
    4. beanFactory.setConversionService( beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
    5. } //为了类型匹配,停止使用临时的类加载器
    6. beanFactory.setTempClassLoader(null); //缓存容器中所有注册的BeanDefinition元数据,以防被修改
    7. beanFactory.freezeConfiguration(); //对配置了lazy-init属性的单态模式Bean进行预实例化处理
    8. beanFactory.preInstantiateSingletons(); }
    9. ConfigurableListableBeanFactory是一个接口,其preInstantiateSingletons方法由其子类DefaultListableBeanFactory提供。 (3).Defa