技术开发 频道

Spring 框架的设计理念与设计模式分析

  Ioc 容器如何工作

  前面介绍了 Core 组件、Bean 组件和 Context 组件的结构与相互关系,下面这里从使用者角度看一下他们是如何运行的,以及我们如何让 Spring 完成各种功能,Spring 到底能有那些功能,这些功能是如何得来的,下面介绍。

  如何创建 BeanFactory 工厂

  正如图 2 描述的那样,Ioc 容器实际上就是 Context 组件结合其他两个组件共同构建了一个 Bean 关系网,如何构建这个关系网?构建的入口就在 AbstractApplicationContext 类的 refresh 方法中。这个方法的代码如下:

  清单 1. AbstractApplicationContext.refresh

public void refresh() throws BeansException, IllegalStateException {
    
synchronized (this.startupShutdownMonitor) {
        
// Prepare this context for refreshing.
        prepareRefresh();
        
// Tell the subclass to refresh the internal bean factory.
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
        
// Prepare the bean factory for use in this context.
        prepareBeanFactory(beanFactory);
        
try {
            
// Allows post-processing of the bean factory in context subclasses.
            postProcessBeanFactory(beanFactory);
            
// Invoke factory processors registered as beans in the context.
            invokeBeanFactoryPostProcessors(beanFactory);
            
// Register bean processors that intercept bean creation.
            registerBeanPostProcessors(beanFactory);
            
// Initialize message source for this context.
            initMessageSource();
            
// Initialize event multicaster for this context.
            initApplicationEventMulticaster();
            
// Initialize other special beans in specific context subclasses.
            onRefresh();
            
// Check for listener beans and register them.
            registerListeners();
            
// Instantiate all remaining (non-lazy-init) singletons.
            finishBeanFactoryInitialization(beanFactory);
            
// Last step: publish corresponding event.
            finishRefresh();
        }
        
catch (BeansException ex) {
            
// Destroy already created singletons to avoid dangling resources.
            destroyBeans();
            
// Reset 'active' flag.
            cancelRefresh(ex);
            
// Propagate exception to caller.
            throw ex;
        }
    }
}

  这个方法就是构建整个 Ioc 容器过程的完整的代码,了解了里面的每一行代码基本上就了解大部分 Spring 的原理和功能了。

  这段代码主要包含这样几个步骤:

  1.注册可能感兴趣的事件

  2.创建 Bean 实例对象

  3.触发被监听的事件

  下面就结合代码分析这几个过程。

  第二三句就是在创建和配置 BeanFactory。这里是 refresh 也就是刷新配置,前面介绍了 Context 有可更新的子类,这里正是实现这个功能,当 BeanFactory 已存在是就更新,如果没有就新创建。下面是更新 BeanFactory 的方法代码:

  清单 2. AbstractRefreshableApplicationContext. refreshBeanFactory

protected final void refreshBeanFactory() throws BeansException {
    
if (hasBeanFactory()) {
        destroyBeans();
        closeBeanFactory();
    }
    
try {
        DefaultListableBeanFactory beanFactory
= createBeanFactory();
        beanFactory.setSerializationId(getId());
        customizeBeanFactory(beanFactory);
        loadBeanDefinitions(beanFactory);
        
synchronized (this.beanFactoryMonitor) {
            
this.beanFactory = beanFactory;
        }
    }
    
catch (IOException ex) {
        
throw new ApplicationContextException(
            
"I/O error parsing bean definition source for "
            
+ getDisplayName(), ex);
    }
}

  这个方法实现了 AbstractApplicationContext 的抽象方法 refreshBeanFactory,这段代码清楚的说明了 BeanFactory 的创建过程。注意 BeanFactory 对象的类型的变化,前面介绍了他有很多子类,在什么情况下使用不同的子类这非常关键。BeanFactory 的原始对象是 DefaultListableBeanFactory,这个非常关键,因为他设计到后面对这个对象的多种操作,下面看一下这个类的继承层次类图:

  图 10. DefaultListableBeanFactory 类继承关系图

 如何创建 BeanFactory 工厂

  从这个图中发现除了 BeanFactory 相关的类外,还发现了与 Bean 的 register 相关。这在 refreshBeanFactory 方法中有一行 loadBeanDefinitions(beanFactory) 将找到答案,这个方法将开始加载、解析 Bean 的定义,也就是把用户定义的数据结构转化为 Ioc 容器中的特定数据结构。

  这个过程可以用下面时序图解释:

  图 11. 创建 BeanFactory 时序图

 如何创建 BeanFactory 工厂

  Bean 的解析和登记流程时序图如下:

  图 12. 解析和登记 Bean 对象时序图

 如何创建 BeanFactory 工厂

  创建好 BeanFactory 后,接下去添加一些 Spring 本身需要的一些工具类,这个操作在 AbstractApplicationContext 的 prepareBeanFactory 方法完成。

  AbstractApplicationContext 中接下来的三行代码对 Spring 的功能扩展性起了至关重要的作用。前两行主要是让你现在可以对已经构建的 BeanFactory 的配置做修改,后面一行就是让你可以对以后再创建 Bean 的实例对象时添加一些自定义的操作。所以他们都是扩展了 Spring 的功能,所以我们要学习使用 Spring 必须对这一部分搞清楚。

  其中在 invokeBeanFactoryPostProcessors 方法中主要是获取实现 BeanFactoryPostProcessor 接口的子类。并执行它的 postProcessBeanFactory 方法,这个方法的声明如下:

  清单 3. BeanFactoryPostProcessor.postProcessBeanFactory

                
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
    
throws BeansException;

  它的参数是 beanFactory,说明可以对 beanFactory 做修改,这里注意这个 beanFactory 是 ConfigurableListableBeanFactory 类型的,这也印证了前面介绍的不同 BeanFactory 所使用的场合不同,这里只能是可配置的 BeanFactory,防止一些数据被用户随意修改。

  registerBeanPostProcessors 方法也是可以获取用户定义的实现了 BeanPostProcessor 接口的子类,并执行把它们注册到 BeanFactory 对象中的 beanPostProcessors 变量中。BeanPostProcessor 中声明了两个方法:postProcessBeforeInitialization、postProcessAfterInitialization 分别用于在 Bean 对象初始化时执行。可以执行用户自定义的操作。

  后面的几行代码是初始化监听事件和对系统的其他监听者的注册,监听者必须是 ApplicationListener 的子类。

0
相关文章