白话解说Spring 容器设计理念
李俊杰
概述
Spring是为了解决企业应用程序开发复杂性而创建的开源框架,书店上关于Spring的书籍汗牛充栋,网上相关的文章连篇累牍,其中有很多写的很不错的,有入门例子的,有问题解决方案的,有环境设置的,有源代码分析的,有spring与其他开源系统集成的,不一而足。本文通过生活白话,不拘泥于Spring源代码和专业术语的束缚,不拘泥于具体的实现细节,类比介绍Spring容器的宏观的设计理念。
让Spring容器走下神坛
Spring容器提供 Spring 框架的基本功能,是工厂模式的实现。换句话说,Spring就是Bean的工厂,管理Bean的生命周期。那如何来设计呢?Spring源代码虽不说是浩如烟海,也让人头晕目眩,如下图所示,我们让Spring容器走下神坛,既然是面向接口编程,用接口来描述框架,不必拘泥于具体实现可能更清晰些。
任何的设计都是这样,有原料,有入口,有加工,也有出口。既然Spring是Bean的容器,是Bean的工厂,那么生产Bean流程是:
1) 原料:bean的配置文件
2) 进料:通过ResourceLoader把xml文本文件读入
3) 初加工:通过BeanDefinitionReader把原料加工成半成品BeanDefinition
4) 精加工:Bean的生产车间BeanFactory把半成品BeanDefinition加工成Bean
5) 入库:成品库SingletonRegistry保存成品Bean,及Bean的标签(beanId),呵呵!你也知道这就是Map的工作了
IOC是Sprng 核心?关键?
Spring容器使用控制反转 (IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开,控制反转(IOC)模式是基于java反射的基本原理。
通常的软件设计,肯定把IOC作为容器的核心,其他外围的功能如bean 的Scope都是基于IOC展开,而Spring设计却只把它放如工具类BeanUtil,这正是Spring的高明之处,虽然IOC是Spring的创建bean的基础,但创建一个bean需要判断是否静态工厂创建,是否有含参数的构造方法,而这些参数也可能是其他对象的实例,创建bean的初始化方法等等,这些不仅仅是bean的IOC所能涵盖的,并且在创建一个bean的过程中可能需要多次迭代调用IOC程序。
综上所述,IOC虽然是Spring的创建Bean的基本原理,但仅是及其重要的一部分,并不是Spring容器的核心,是Spring创建bean的比不可少的工具。IOC是Spring容器的关键,而不是核心。
Interface分级设计
接口的分级设计,是针对不同的客户给予不同级别的产品。不同等级的接口关注点也各有不同,就像产品也分为多个级别,如高级产品、中级产品、初级产品分别对应于不同的客户群,或者如同银行的客户渠道有银行卡,柜台,网银,手机终端,ATM机等等。同样接口也分为内部接口和外部接口,就如同有些接口可能永远不被外部用户所知,仅仅是内部使用,就像工厂内部多个车间之间的内部产品。
org.springframework.beans.factory. BeanFactory是Spring的顶级Interface,其中只有getBean系列,containsBean,isPrototype,isSingleton,getType等成品Bean的基本方法。
org.springframework.beans.factory. ListableBeanFactory是Factory的管理方法如containsBeanDefinition,getBeanDefinitionCount,getBeanDefinitionNames,getBeanNamesForType系列,getBeansOfType系列,ListableBeanFactory是针对BeanDefinition半成品的。
而ApplicationContext接口除了集成ListableBeanFactory接口外,还继承了ResourcePatternResolver,HierarchicalBeanFactory,ApplicationEventPublisher,MessageSource的功能,如在资源处理(国际化处理),事件传递,及各应用层之间的context实现。同样是对外的接口,Spring更建议采用ApplicationContext的原因也就在这儿,ApplicationContext更像是针对VIP客户的产品。
Interface扩展设计
Spring设计是开放性的设计思路,是值得我们做架构设计人员学习的,如下图所示:
com.springframework.beans.factory (淡黄色背景) | |BeanFactory |ListableBeanFactory |ConfigrableListableBeanFactory |DefaultListableBeanFactory
|
|
com.springframework.context (棕红色背景) | ApplicationContext ConfigrableApplicationContext
|
|
org.springframework.context (黄色背景) | .support | AbstractApplicationContext AbstractRefreshableApplicationContext AbstractXmlApplicationContext ClassPathXmlApplicationContext
|
org.springframework.web.context (绿色背景) | WebApplicationContext ConfigrableWebApplicationContext |
|
org.springframework.web.context (浅蓝色背景) | .support | AbstractRefreshableWebApplicationContext XmlWebApplicationContext
|
总结如下:
1) 不同的包下面放不同的东西,好像是废话啊!上层包放接口,下层包放实现的抽象类及实体类。如contex.support包下面放实现context包下面的接口的抽象类及实现类。
2) 为了适应WEB级别的ApplicationContext,创建了WebApplicationContext的接口,该接口继承了ApplicationContext,又添加了WEB层的个性化方法如getServletContext及属性。现在终于明白了在接口间的“extends”的含义,绝对是对上层接口的“扩展“,扩展的目的是适应更具体化的环境。就如同因为国家大,情况复杂,中央的政策相对都是比较抽象的,而地方政策必须结合地方的特色,既要满足中央政策的要求,即实现中央政策的接口,又要根据本地特殊情况,扩展个性化的政策,即地方政策接口,从而更具有可操作性。
3) 在org.springframework.web.context.support.AbstractRefreshableWebAppplicationContext类是既实现了ConfigrableWebApplicationContext接口,即实现WEB的个性化特色,又继承了org.springframework.context.support.AbstractRefreshableApplicationContext类。借助了已有的类,实现了架构上的复用,这就像制定政策既要满足地方上的特色,又可以参照其他地区现成的政策经验。呵呵!在实际工作中,也会常常有这样的设计。
努力,在于我热爱我的事业,与中国的软件一起走向成熟,走向世界。
联系作者:lijj_72@hotmail.com