`

Spring框架的设计理念与设计模式(6)-Ioc容器及BeanFactory工厂

阅读更多
关键词:Spring,Ioc,Bean,Context,BeanFactory工厂
上一章:Spring框架的设计理念与设计模式(5)-Core组件                 http://javapub.iteye.com/blog/751627
下一章:Spring框架的设计理念与设计模式(7)-Spring中AOP特性与实现    http://javapub.iteye.com/blog/751642

Ioc容器如何工作

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

如何创建BeanFactory工厂

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& nbsp;the context.  
 
            invokeBeanFactoryPostProcessors(beanFactory);  
 
            // Register bean processors that intercept bean crea tion.  
 
            registerBeanPostProcessors (beanFactory);  
 
            // Initialize message source for this context.  
 
            initMessageSource();  
 
            // Initialize event multicaster for this context.  
 
            initApplicationEventMulticaster();  
 
            // Initialize other special beans in specific contex t 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 dangl ing resources.  
 
            destroyBeans();  
 
            // Reset 'active' flag.  
 
            cancelRefresh(ex);  
 
            // Propagate exception to caller.  
 
            throw ex;  
 
        }  
 
    }  
 
}  

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

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

◆构建BeanFactory,以便于产生所需的“演员”

◆注册可能感兴趣的事件

◆创建Bean实例对象

◆触发被监听的事件

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

第二三句就是在创建和配置BeanFactory。这里是refresh也就是刷新配置,前面介绍了Context有可更新的子类,这里正是实现这个功能,当BeanFactory已存在是就更新,如果没有就新创建。下面是 更新BeanFactory的方法代码:
清单2. AbstractRefreshableApplicationContext. refreshBeanFactory
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& nbsp;the context.  
 
            invokeBeanFactoryPostProcessors(beanFactory);  
 
            // Register bean processors that intercept bean crea tion.  
 
            registerBeanPostProcessors (beanFactory);  
 
            // Initialize message source for this context.  
 
            initMessageSource();  
 
            // Initialize event multicaster for this context.  
 
            initApplicationEventMulticaster();  
 
            // Initialize other special beans in specific contex t 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 dangl ing resources.  
 
            destroyBeans();  
 
            // Reset 'active' flag.  
 
            cancelRefresh(ex);  
 
            // Propagate exception to caller.  
 
            throw ex;  
 
        }  
 
    }  
 
}  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& nbsp;parsing bean definition source for "  
 
                       + getDisplayName (), ex);  
 
    }  
 
} 

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


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

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

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

创建好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的子类。

如何创建Bean实例并构建Bean的关系网


下面就是Bean的实例化代码,是从finishBeanFactoryInitialization方法开始的。
清单4.AbstractApplicationContext.finishBeanFactoryInitialization
protected void finishBeanFactoryInitialization(  
 
        ConfigurableListableBeanFactory beanFactory) {  
 
   
 
    // Stop using the temporary ClassLoader for type matching.  
 
    beanFactory.setTempClassLoader(null);  
 
   
 
    // Allow for caching all bean definition metadata, not expecting further changes .  
 
    beanFactory.freezeConfiguration();  
 
   
 
    // Instantiate all remaining (non-lazy-init) singletons.  
 
    beanFactory.preInstantiateSingletons();  
 
} 

从上面代码中可以发现Bean的实例化是在BeanFactory中发生的。preInstantiateSingletons方法的代码如下:

清单5.DefaultListableBeanFactory.preInstantiateSingletons
public void preInstantiateSingletons() throws BeansException {  
 
    if (this.logger.isInfoEnabled()) {  
 
        this.logger.info("Pre- instantiating singletons in " + this);  
 
    }  
 
    synchronized (this.beanDefinitionMap) {  
 
        for  (String beanName : this.beanDefinitionNames) {  
 
            RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);  
 
            if (!bd.isAbstract()  && bd.isSingleton()  
 
                && !bd.isLazyInit()) {  
 
                if  (isFactoryBean(beanName)) {  
 
                    final FactoryBean factory =  
 
                        (FactoryBean)  getBean(FACTORY_BEAN_PREFIX+ beanName);  
 
                    boolean isEagerInit;  
 
                    if (System.getSecurityManager()  != null  
 
                        &&  ;factory instanceof SmartFactoryBean) {  
 
                        isEagerInit = AccessController.doPrivileged(  
 
                          &nb sp; new PrivilegedAction<Boolean>() {  
 
                          &nb sp; public Boolean run() {  
 
 return ((SmartFactoryBean)  factory).isEagerInit();  
 
                          &nb sp; }  
 
                        }, getAcce ssControlContext());  
 
                    }  
 
                    else {  
 
                        isEagerInit = factory instanceof SmartFactoryBean  
 
                          &nb sp; && ((SmartFactoryBean) factory).isEagerInit();  
 
                    }  
 
                    if (isEagerInit) {  
 
                        getBean (beanName);  
 
                    }  
 
                }  
 
                else {  
 
                    getBean(beanName);  
 
                }  
 
            }  
 
        }  
 
    }  
} 

这里出现了一个非常重要的Bean——FactoryBean,可以说Spring一大半的扩展的功能都与这个Bean有关,这是个特殊的Bean 他是个工厂Bean,可以产生Bean的Bean,这里的产生Bean是指 Bean的实例,如果一个类继承FactoryBean用户可以自己定义产生实例对象的方法只要实现他的getObject方法。然而在Spring内部这个Bean的实例对象是FactoryBean,通过调用这个对象的getObject方 法就能获取用户自定义产生的对象,从而为Spring提供了很好的扩展性。Spring获取FactoryBean本身的对象是在前面加上&来完成的。

如何创建Bean的实例对象以及如何构建Bean实例对象之间的关联关系式Spring中的一个核心关键,下面是这个过程的流程图。

如果是普通的Bean就直接创建他的实例,是通过调用getBean方法。下面是创建Bean实例的时序图:

还有一个非常重要的部分就是建立Bean对象实例之间的关系,这也是Spring框架的核心竞争力,何时、如何建立他们之间的关系请看下面的时序图:


Ioc容器的扩展点

现在还有一个问题就是如何让这些Bean对象有一定的扩展性,就是可以加入用户的一些操作。那么有哪些扩展点呢?Spring又是如何调用到这些扩展点的?

对Spring的Ioc容器来说,主要有这么几个。BeanFactoryPostProcessor,BeanPostProcessor。他们分别是在构建BeanFactory和构建Bean对象时调用。还有就是InitializingBean和DisposableBean 他们分别是在Bean实例创建和销毁时被调用。用户可以实现这些接口中定义的方法,Spring就会在适当的时候调用他们。还有一个是 FactoryBean他是个特殊的Bean,这个Bean可以被用户更多的控制。

这些扩展点通常也是我们使用Spring来完成我们特定任务的地方,如何精通Spring就看你有没有掌握好Spring有哪些扩展点,并且如何使用他们,要知道如何使用他们就必须了解他们内在的机理。可 以用下面一个比喻来解释。

我们把Ioc容器比作一个箱子,这个箱子里有若干个球的模子,可以用这些模子来造很多种不同的球,还有一个造这些球模的机器,这个机器可以产生球模。那么他们的对应关系就是BeanFactory就是 那个造球模的机器,球模就是Bean,而球模造出来的球就是Bean的实例。那前面所说的几个扩展点又在什么地方呢?BeanFactoryPostProcessor对应到当造球模被造出来时,你将有机会可以对其做出设 当的修正,也就是他可以帮你修改球模。而InitializingBean和DisposableBean是在球模造球的开始和结束阶段,你可以完成一些预备和扫尾工作。BeanPostProcessor就可以让你对球模造出来的球做出 适当的修正。最后还有一个FactoryBean,它可是一个神奇的球模。这个球模不是预先就定型了,而是由你来给他确定它的形状,既然你可以确定这个球模型的形状,当然他造出来的球肯定就是你想要的 球了,这样在这个箱子里尼可以发现所有你想要的球

Ioc容器如何为我所用

前面的介绍了Spring容器的构建过程,那Spring能为我们做什么,Spring的Ioc容器又能做什么呢?我们使用Spring必须要首先构建Ioc容器,没有它Spring无法工作,ApplicatonContext.xml就是Ioc 容器的默认配置文件,Spring的所有特性功能都是基于这个Ioc容器工作的,比如后面要介绍的AOP。

Ioc它实际上就是为你构建了一个魔方,Spring为你搭好了骨骼架构,这个魔方到底能变出什么好的东西出来,这必须要有你的参与。那我们怎么参与?这就是前面说的要了解Spring中那有些扩展点 ,我们通过实现那些扩展点来改变Spring的通用行为。至于如何实现扩展点来得到我们想要的个性结果,Spring中有很多例子,其中AOP的实现就是 Spring本身实现了其扩展点来达到了它想要的特性功能 ,可以拿来参考。

目录--Spring框架的设计理念与设计模式
Spring框架的设计理念与设计模式(1)-Spring的架构             http://javapub.iteye.com/blog/751539
Spring框架的设计理念与设计模式(2)-Spring的设计理念         http://javapub.iteye.com/blog/751545
Spring框架的设计理念与设计模式(3)-Bean组件                 http://javapub.iteye.com/blog/751550
Spring框架的设计理念与设计模式(4)-Context组件              http://javapub.iteye.com/blog/751625
Spring框架的设计理念与设计模式(5)-Core组件                 http://javapub.iteye.com/blog/751627
Spring框架的设计理念与设计模式(6)-Ioc容器及BeanFactory工厂 http://javapub.iteye.com/blog/751635
Spring框架的设计理念与设计模式(7)-Spring中AOP特性与实现    http://javapub.iteye.com/blog/751642
Spring框架的设计理念与设计模式(8)-代理模式                 http://javapub.iteye.com/blog/751652
Spring框架的设计理念与设计模式(9)-策略模式                 http://javapub.iteye.com/blog/751653
分享到:
评论
1 楼 TheUniqueGirl 2015-04-13  
Spring框架的设计理念与设计模式分析:http://www.docin.com/p-1121445526.html

相关推荐

    SpringFramework常见知识点.md

    - Spring主要使用了哪些设计模式? - Spring IOC容器的配置方式有哪些? - BeanFactory和ApplicationContext的区别是什么? - 什么是IOC容器和DI依赖注入? - Spring依赖注入的方式有几种? - 一个bean的定义包含...

    Spring-IOC::label:手写实现了Spring框架的基本功能,存在了注解以及xml配置,并且实现了引用注入等功能,还实现了SpringMVC的简单功能

    我的春天Spring IOC容器简单实现,实现了一些基本的核心功能以及简单的MVC基本框架及映射访问说明文档目前已实现: xml注入注解注入简单MVC功能注入支持递归注入属性注入引用注入(但未解决循环依赖)注解配置单例...

    25个经典的Spring面试问答

    什么是Spring框架Spring框架有哪些主要模块 使用Spring框架能带来哪些好处 什么是控制反转IOC什么是依赖注入 请解释下Spring框架中的IoC BeanFactory和ApplicationContext有什么...Spring 框架中都用到了哪些设计模式

    Spring高级之注解驱动开发视频教程

    n 设计模式-工厂模式 n 基础应用-入门案例 n 基础应用-常用注解使用场景介绍及入门 n 高级特性-自定义BeanNameGenerator n 高级特性-自定义TypeFilter n 高级特性-ImportSelector和ImportBeanDefinitionRegistrar的...

    Spring面试专题.pdf

    1、什么是 Spring 框架?Spring 框架有哪些主要模块? 2、使用 Spring 框架能带来哪些好处? 3、什么是控制反转(IOC)?什么是依赖注入? 4、请解释下 Spring 框架中的 IoC?...25、Spring 框架中都用到了哪些设计模式?

    Spring面试题.zip

    1、什么是 Spring 框架?Spring 框架有哪些主要模块? 2、使用 Spring 框架能带来哪些好处? 3、什么是控制反转(IOC)?什么是依赖注入? 4、请解释下 Spring 框架中的 IoC?...25、Spring 框架中都用到了哪些设计模式?

    xmljava系统源码-Myioc:这是一个简单的IoC容器实现

    对于JAVA知识也算是比较了解了,IoC,反射,设计模式等知识都能讲清楚,但是感觉由于平时使用框架做Web后台开发的原因,明明每天都在接触这些东西,但是又没有真正在使用它们,只是使用了Spring等框架基于它们来实现...

    Spring面试题

    下一个最高级抽象是 BeanFactory 接口,它是工厂设计模式的实现,允许通过名称创建和检索对象。BeanFactory 也可以管理对象之间的关系。 BeanFactory 支持两个对象模型。 □ 单态 模型提供了具有特定名称的对象的...

    高级开发spring面试题和答案.pdf

    Spring中用到的设计模式; SPI 机制(Java SPI 实际上是“基于接口的编程+策略模式+配置文件”组合实现的动态加载机制), 很多地方有用到: AOP Spring的AOP的底层实现原理; 为什么jdk动态代理是必须是接口 两种动态...

    java-advance:java进阶,包含 常用设计模式、线程和并发、spring核心代码、mybatis核心代码、springboot2.0、springcloud G版本、docker的使用、各类面试题

    java进阶源码分析专题常用设计模式线程与并发锁的使用深度理解synchronized、volatile、cas手写ASQSpring5IOC容器设计原理及高级特性AOP设计原理FactoryBean与BeanFactorySpring事务处理机制Spring JDK动态代理...

    春天来了,继续手写自己的Spring,从0到1,从IOC到DI、AOP、MVC四个阶段,项目已经传到了github和码云上面

    熬了半个多月的时间,每天坐在电脑面前十几个小时,从Spring官网拉下来了spring-framework这个项目的源码,边看源码,边从网上找资料,整个项目中使用的设计模式也是非常的经典,如工厂模式:BeanFactory,代理模式...

    积分管理系统java源码-knowledge:这是我的知识,包括我所有已知的

    IOC容器设计原理及高级特性 AOP设计原理 FactoryBean和BeanFactory Spring事务处理机制 Spring JDBC Spring MVC九大组件 手动实现Spring MVC Spring5新特性 Mybatis 代码自动生成器 mybatis关联查询和嵌套查询 缓存...

    超级玛丽源码Java-Spring5:春天5

    (1)BeanFactory:IOC容器基本实现,是Spring内部的使用接口,不提供开发人员进行使用 *加载配置文件时候不会创建对象,在获取对象(使用)才去创建对象 (2)ApplicationContext:BeanFactory,接口的子接口,提供更多更...

    Java Web程序设计教程

    5.1.2mvc设计模式 81 5.1.3struts2框架的mvc架构 82 5.2struts2概览 84 5.2.1struts2的工作流程 84 5.2.2struts2的简单应用 85 5.3struts2基础 87 5.3.1action详解 88 5.3.2结果与视图 91 5.3.3struts.xml的...

    J2EE应用开发详解

    246 14.5.2 CORBA和RMI的互操作 247 14.6 小结 248 第15章 Spring框架 249 15.1 Spring 2.0的体系结构 249 15.2 Ioc容器 250 15.2.1 BeanFactory 250 15.2.2 ApplicationContext 252 15.2.3 Beans的生命周期过程 253...

Global site tag (gtag.js) - Google Analytics