多图详解Spring框架的设计理念与设计模式_第1页
多图详解Spring框架的设计理念与设计模式_第2页
多图详解Spring框架的设计理念与设计模式_第3页
多图详解Spring框架的设计理念与设计模式_第4页
多图详解Spring框架的设计理念与设计模式_第5页
已阅读5页,还剩36页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、Spring作为现在最优秀的框架之一,已被广泛的使用,51CTC也曾经针对Spring框架中的JDBC应用做过报道。本文将从另外一个视角试图剖析出Spring框架的作者设计 Spring框架的骨骼架构的设计理念。Rod Johson 在 2002 年编著的Expert one to one J2EE design and development 一书中,对 JavaEE正统框架臃肿、低效、脱离现实的种种现状提岀了质疑,并积极寻求探索革新之道。以此书为指导思想,他编写了 interface21框架,这是一个力图冲破 Java EE传统开发的困境,从实际需求出发,着眼于轻便、灵巧,易于开发、测试和

2、部署的轻量级开发框架。Spring框架即以interface21框架为基础,经过重新设计,并不断丰富其内涵,于 2004年3月24日,发布了 1.0正式版。同年他又推出了一部堪称经典的力作Expert one-to-one J2EE Development without EJB ,该书在 Java世界掀起了轩然大波,不断改变着Java开发者程序设计和开发的思考方式。在该书中,作者根据自己多年丰富的实践经验,重臃肿的结构进行了逐一的分析和否定,并分别以简洁实用的方式替换之。至此一战功成,对EJB的各种笨Rod Johnson成为一个改变Java世界的大师级人物传统J2EE应用的开发效率低,应用

3、服务器厂商对各种技术的支持并没有真正统一,导致J2EE的应用没有真正实现 Write Once及Run Anywhere的承诺。Spring作为开源的中间件,独立于各种应用服务器, 甚至无须应用服务器的支持,也能提供应用服务器的功能,如声明式事务等。Spring致力于J2EE应用的各层的解决方案,而不是仅仅专注于某一层的方案。可以说Spring是企业应用开发的“一站式”选择,并贯穿表现层、业务层及持久层。然而,Spring并不想取代那些已有的框架,而与它们无缝地整合。Spring简介Spring是一个开源框架,它由RodJohnson创建。它是为了解决企业应用开发的复杂性而创建的。Spring

4、使用基本的JavaBean来完成以前只可能由 EJB完成的事情。然而,Spring的用途不仅限于服务器端的开 发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。目的:解决企业应用开发的复杂性功能:使用基本的JavaBean代替EJB,并提供了更多的企业应用功能范围:任何Java应用简单来说,Spring是一个轻量级的控制反转(loC)和面向切面(AOP)的容器框架。轻量一一从大小与开销两方面而言Spring都是轻量的。完整的 Spring框架可以在一个大小只有1MB多的JAR文件里发布。并且 Spring所需的处理开销也是微不足道的。此外, Spring是非

5、侵入式的:典型地, Spring应用中的对象不依赖于 Spring的特定类。控制反转一一Spring通过一种称作控制反转(IoC )的技术促进了松耦合。当应用了 IoC,一个对象依赖 的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。你可以认为IoC与JNDI相反一一不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它。面向切面一一Spring提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例 如审计(auditing )和事务()管理)进行内聚性的开发。应用对象只实现它们应该做的一一完成业务逻 辑一一仅此而已。它们并

6、不负责(甚至是意识)其它的系统级关注点,例如日志或事务支持。容器一一Spring包含并管理应用对象的配置和生命周期,在这个意义上它是一种容器,你可以配置你的 每个bean如何被创建基于一个可配置原型(prototype ),你的bean可以创建一个单独的实例或者每次需要时都生成一个新的实例一一以及它们是如何相互关联的。然而,Spring不应该被混同于传统的重量级的EJB容器,它们经常是庞大与笨重的,难以使用。框架一一Spring可以将简单的组件配置、组合成为复杂的应用。在Spring中,应用对象被声明式地组合,典型地是在一个 XML文件里。Spring也提供了很多基础功能(事务管理、持久化框架

7、集成等等),将 应用逻辑的开发留给了你。所有 Spring 的这些特征使你能够编写更干净、更可管理、并且更易于测试的代码。它们也为 Spring 中的 各种模块提供了基础支持。为什么需要 Spring你可能正在想“ Spring不过是另外一个的framework。当已经有许多开放源代码(和专有)J2EEframework 时,我们为什么还需要 Spring Framework ?Spring 是独特的 , 因为若干个原因 :它定位的领域是许多其他流行的framework没有的。Spring关注提供一种方法管理你的业务对象。 Spring是全面的和模块化的。Spring有分层的体系结构,这意味着

8、你能选择使用它孤立的任何部分,它 的架构仍然是内在稳定的。因此从你的学习中,你可得到最大的价值。例如, 你可能选择仅仅使用 Spring来简单化JDBC的使用,或用来管理所有的业务对象。它的设计从底部帮助你编写易于测试的代码。 Spring 是用于测试驱动工程的理想的 framework 。Spring 对你的工程来说,它不需要一个以上的framework 。 Spring 是潜在地一站式解决方案,定位于与典型应用相关的大部分基础结构。它也涉及到其他 framework 没有考虑到的内容。Spring 带给我们什么方便解耦, 简化开发 , 通过 Spring 提供的 IoC 容器,我们可以将对

9、象之间的依赖关系交由 Spring 进行控 制,避免硬编码所造成的过度程序耦合。有了 Spring ,用户不必再为单实例模式类、属性文件解析等这些 很底层的需求编写代码,可以更专注于上层的应用。AOP编程的支持通过Spring提供的AOP功能,方便进行面向切面的编程,许多不容易用传统OOP实现的功能可以通过 AOP轻松应付。声明式事务的支持在 Spring 中,我们可以从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活地进行事务的管理, 提高开发效率和质量。方便程序的测试可以用非容器依赖的编程方式进行几乎所有的测试工作,在 Spring 里, 测试不再是昂贵的操作, 而是随手 可做的事情。

10、方便集成各种优秀框架Spring 不排斥各种优秀的开源框架,相反, Spring 可以降低各种框架的使用难度, Spring 提供了对各种 优秀框架(如 Struts,Hibernate 、Hession 、Quartz )等的直接支持。降低 Java EE API 的使用难度Spring 对很多难用的 Java EEAP(I 如 JDBC, JavaMail ,远程调用等) 提供了一个薄薄的封装层, 通过 Spring 的简易封装,这些 Java EE API 的使用难度大为降低。Java 源码是经典学习范例Spring 的源码设计精妙、结构清晰、匠心独用,处处体现着大师对 Java 设计模

11、式灵活运用以及对 Java 技 术的高深造诣。 Spring 框架源码无疑是 Java 技术的最佳实践范例。 如果想在短时间内迅速提高自己的 Java 技术水平和应用开发水平,学习和研究 Spring 源码将会使你收到意想不到的效果。Spring 框架的好处在我们进入细节以前,让我们看一下 Spring 可以给一个工程带来的一些好处 :Spring能有效地组织你的中间层对象,无论你是否选择使用了 EJB如果你仅仅使用了 Struts或其他的 包含了 J2EE 特有 APIs 的 framework ,你会发现 Spring 关注了遗留下的问题,。Spring 能消除在许多工程上对 Single

12、ton 的过多使用。根据我的经验,这是一个主要的问题,它减少了 系统的可测试性和面向对象特性。Spring 能消除使用各种各样格式的属性定制文件的需要 , 在整个应用和工程中,可通过一种一致的方法 来进行配置。 曾经感到迷惑, 一个特定类要查找迷幻般的属性关键字或系统属性 , 为此不得不读 Javadoc 乃 至源编码吗?有了 Spring ,你可很简单地看到类的 JavaBean 属性。倒置控制的使用 ( 在下面讨论 )帮助完 成这种简化。Spring 能通过接口而不是类促进好的编程习惯,减少编程代价到几乎为零。Spring 被设计为让使用它创建的应用尽可能少的依赖于他的 APIs 。在 S

13、pring 应用中的大多数业务对象 没有依赖于 Spring 。使用 Spring 构建的应用程序易于单元测试。Spring能使EJB的使用成为一个实现选择,而不是应用架构的必然选择。你能选择用POJOs或 local EJBs来实现业务接口,却不会影响调用代码。Spring帮助你解决许多问题而无需使用EJB。Spring能提供一种EJB的替换物,它们适于许多web应用。例如Spring能使用AOP提供声明性事务而不通过使用EJB容器,如果你仅仅需要与单个的数据库打交道,甚至不需要JTA实现。Spring为数据存取提供了一致的框架,不论是使用JDBC或0/R mapping产品(如Hibern

14、ate )。Spring 确实使你能通过最简单可行的解决办法解决你的问题。这些特性是有很大价值的。总结起来, Spring 有如下优点:低侵入式设计,代码污染极低独立于各种应用服务器,可以真正实现 Write Once,Run Anywhere 的承诺Spring 的 DI 机制降低了业务对象替换的复杂性Spring 并不完全依赖于 Spring ,开发者可自由选用 Spring 框架的部分或全部Spring 能做什么?Spring 提供许多功能 , 在此我将快速地依次展示其各个主要方面。首先 , 让我们明确 Spring 范围。尽 管 Spring 覆盖了许多方面,但我们已经有清楚的概念,它

15、什么应该涉及和什么不应该涉及。Spring 的主要目的是使J2EE易用和促进好编程习惯。Spring 不重新开发已有的东西。因此,在 Spring 中你将发现没有日志记录的包 , 没有连接池 ,没有分 布事务调度。这些均有开源项目提供 ( 例如 Commons Logging 用来做所有的日志输出,或 Commons DBCP 用来作数据连接池 ), 或由你的应用程序服务器提供。因为同样的的原因,我们没有提供O/R mapping 层,对此,已有有好的解决办法如 Hibernate 和 JDO。Spring 的目标是使已存在的技术更加易用。例如 , 尽管我们没有底层事务协调处理,但我们提供了一

16、个抽象层覆盖了 JTA或任何其他的事务策略。Spring 没有直接和其他的开源项目竞争,除非我们感到我们能提供新的一些东西。例如,象许多开发 人员,我们从来没有为 Struts 高兴过,并且感到在 MVC web framework 中还有改进的余地。在某些领域, 例如轻量级的IoC容器和AOP框架,Spring有直接的竞争,但是在这些领域还没有已经较为流行的解决方 案。 (Spring 在这些区域是开路先锋。 )Spring也得益于内在的一致性。所有的开发者都在唱同样的的赞歌,基础想法依然是ExpertOne-on-One J2EE设计与开发的那些。并且我们已经能够使用一些主要的概念,例如倒

17、置控制,来处理多个领域。Spring在应用服务器之间是可移植的。当然保证可移植性总是一次挑战,但是我们避免任何特定平 台或非标准化,并且支持在 WebLogic,Tomcat,Resin,JBoss,WebSphere和其他的应用服务器上的用户。Spring作为现在最优秀的框架之一,已被广泛的使用,51CTO也曾经针对Spring框架中的JDBC应用做过报道。本文将从另外一个视角试图剖析出Spring框架的作者设计Spring框架的骨骼架构的设计理念,有那几个核心组件?为什么需要这些组件?它们又是如何结合在一起构成Spring的骨骼架构? Spring的AOP特性又是如何利用这些基础的骨骼架构

18、来工作的?Spring中又使用了那些设计模式来完成它的这种设计的?它的这种 设计理念对对我们以后的软件设计有何启示?本文将详细解答这些问题。Spring的骨骼架构Spring总共有十几个组件,但是真正核心的组件只有几个,下面是 Spring框架的总体架构图:图1.Spring框架的总体架构图从上图中可以看出 Spring框架中的核心组件只有三个:Core、Context和Beans。它们构建起了整个Spring的骨骼架构。没有它们就不可能有AOP Web等上层的特性功能。下面也将主要从这三个组件入手分析 Spring。Spring的设计理念前面介绍了 Spring的三个核心组件,如果再在它们三

19、个中选出核心的话,那就非Beans组件莫属了,为何这样说,其实 Spring 就是面向 Bean 的编程(BOP,BeanOriented Programming) , Bean在 Spring 中 才是真正的主角。Bean在Spring中作用就像Object对OOP的意义一样,没有对象的概念就像没有面向对象编程, Spring 中没有Bean也就没有Spring存在的意义。就像一次演出舞台都准备好了但是却没有演员一样。为什么要Bean这种角色Bean或者为何在Spring如此重要,这由Spring框架的设计目标决定,Spring为何如此流行,我们用Spring的原因是什么,想想你会发现原来

20、Spring解决了一个非常关键的问题他可以让 你把对 象之间的依赖关系转而用配置文件来管理,也就是他的依赖注入机制。而这个注入关系在一个叫loc容器中管理,那loc容器中有又是什么就是被 Bean包裹的对象。Spring正是通过把对象包装在 Bean中而达到 对这些对象管理以及一些列额外操作的目的。它这种设计策略完全类似于Java实现00F的设计理念,当然了 Java本身的设计要比 Spring复杂太多太多,但是都是构建一个数据结构,然后根据这个数据结构设计他的生存环境,并让它在这个环境中按照一定的规律在不停的运动,在它们的不停运动中设计一系列与环境或者与其他个体完成信息交换。这样想 来回过头

21、想想我们用到的其他框架都是大慨类似的设计理念。核心组件如何协同工作前面说Bean是Spring中关键因素,那 Context和Core又有何作用呢?前面吧 Bean比作一场演出中 的演员的话,那Context就是这场演出的舞台背景,而Core应该就是演出的道具了。只有他们在一起才能具备能演出一场好戏的最基本的条件。当然有最基本的条件还不能使这场演出脱颖而出,还要他表演的节 目足够的精彩,这些节目就是Spring能提供的特色功能了。我们知道Bean包装的是Object,而Object必然有数据,如何给这些数据提供生存环境就是Context要解决的问题,对Context来说他就是要发现每个 Bea

22、n之间的关系,为它们建立这种关系并且要维护好 这 种关系。所以Context就是一个Bean关系的集合,这个关系集合又叫 loc容器,一旦建立起这个loc容器 后Spring就可以为你工作了。那 Core组件又有什么用武之地呢?其实 Core就是发现、建立和维护每 个 Bean之间的关系所需要的一些列的工具,从这个角度看来,Core这个组件叫Util更能让你理解。它们之间可以用下图来表示:图2.三个组件关系核心组件详解这里将详细介绍每个组件内部类的层次关系,以及它们在运行时的时序顺序。我们在使用Spring是应该注意的地方。Bean组件前面已经说明了 Bean组件对Spring的重要性,下面看

23、看 Bean这个组件式怎么设计的。Bean组件在Spring的org.springframework.beans 包下。这个包下的所有类主要解决了三件事:Bean的定义、Bean的创建以及对Bean的解析。对Spring的使用者来说唯一需要关心的就是Bean的创建,其他两个由 Spring在内部帮你完成了,对你来说是透明的。SpringBean的创建时典型的工厂模式,他的顶级接口是BeanFactory,下图是这个工厂的继承层次关系:图4.Bean工厂的继承关系BeanFactory 有三个子类:ListableBeanFactory 、HierarchicalBeanFactory 和 Au

24、towire Capable Bean Factory。但是从上图中我们可以发现最终的默认实现类是DefaultListableBeanFactory ,他实 现了所有的接口。那为何要定义这么多层次的接口呢?查阅这些接口的源码和说明发现,每个接口都有他使用的场 合,它主要是为了区分在Spring内部在操作过程中对象的传递和转化过程中,对对象的数据访问所做的限制。例如ListableBeanFactory接口表示这些Bean是可列表的,而HierarchicalBeanFactory表示的是这些Bean是有继承关系的,也就是每个Bean有可能有父 Bean。AutowireCapableBean

25、Factory 接口定义Bean的自动装配规则。这四个接口共同定义了Bean的集合、Bean之间的关系、以及 Bean行为。Bean的定义主要有 BeanDefinition 描述,如下图说明了这些类的层次关系: I i:. Attributes&or匸11IBeuiDef ini ti on.:i R otBefuiDefi ni ti qti图5.Bean定义的类层次关系图Bean的定义就是完整的描述了在Spring的配置文件中你定义的节点中所有的信息,包括各种子节点。当Spring成功解析你定义的一个节点后,在Spring的内部他就被转化 成BeanDefinition 对象。以后所有的

26、操作都是对这个对象完成的。Bean的解析过程非常复杂,功能被分的很细,因为这里需要被扩展的地方很多,必须保证有足够的灵活性,以应对可能的变化。Bean的解析主要就是对 Spring配置文件的解析。这个解析过程主要通过下图中的类完成:图6.Bean的解析类当然还有具体对tag的解析这里并没有列出。Context 组件Context 在 Spring 的 org.springframework.context包下,前面已经讲解了Context 组件在 Spring中的作用,他实际上就是给Spring提供一个运行时的环境,用以保存各个对象的状态。下面看一下这个环境是如何构建的。Application

27、context 是Context的顶级父类,他除了能标识一个应用环境的基本信息外,他还继承了 五个接口,这五个接口主要是扩展了Context的功能。下面是 Context的类结构图:uiL?ibditar1 %.: |tul Lra J.起 T Jijhau L4M砂 lUfrUhU川*血炖乩社1程1晒”屮仆盯耐i 1 *iwi片 1 -1 1 ihl lilt adiitarR rw v_ f hi id i K i rfal Ir iii aif11! aft1i: h 丐I調淌弊! *!J*.*1 ihBI图7.Context相关的类结构图从上图中可以看出 Applicationcont

28、ext 继承了 BeanFactory,这也说明了 Spring容器中运行的主体 对象是 Bean,另外 ApplicationContext 继承了 ResourceLoader 接口,使得 ApplicationContext 可以访 问 到任何外部资源,这将在 Core中详细说明。ApplicationContext的子类主要包含两个方面:ConfigurableApplicationContext表示该 Context是可修改的,也就是在构建Context中用户可以动态添加或修改已有的配置信息,它下面又有多个子类,其中最经常使用的是可更新的Context,即AbstractRefres

29、hableApplicationContext类。WebApplicationContext 顾名思义,就是为 web准备的Context他可以直接访问到 ServletContext , 通常情况下,这个接口使用的少。再往下分就是按照构建Context的文件类型,接着就是访问Context的方式。这样一级一级构成了完整的Context等级层次。总体来说ApplicationContext必须要完成以下几件事:标识一个应用环境利用BeanFactory创建Bean对象保存对象关系表能够捕获各种事件Context作为Spring的Ioc容器,基本上整合了Spring的大部分功能,或者说是大部分功

30、能的基础。Core组件Core组件作为Spring的核心组件,他其中包含了很多的关键类,其中一个重要组成部分就是定义了 资源的访问方式。这种把所有资源都抽象成一个接口的方式很值得在以后的设计中拿来学习。下面就重要看一下这个部分在Spring的作用。下图是Resource相关的类结构图:图8.Resource相关的类结构图从上图可以看出Resource接口封装了各种可能的资源类型,也就是对使用者来说屏蔽了文件类型的不 同。对资源的提供者来说,如何把资源包装起来交给其他人用这也是一个问题,我们看到Resource接口继承了 InputStreamSource 接口,这个接口中有个 getlnput

31、Stream 方法,返回的是Inputstream 类。这样 所有的资源都被可以通过Inputstream这个类来获取,所以也屏蔽了资源的提供者。另外还有一个问题就 是加载资源的问题,也就是资源的加载者要统一,从上图中可以看出这个任务是由ResourceLoader接口完成,他屏蔽了所有的资源加载者的差异,只需要实现这个接口就可以加载所有的资源,他的默认实现是DefaultResourceLoader下面看一下Context和Resource是如何建立关系的?首先看一下他们的类关系图:IIi Ii ii greII I l iiiII I IiilI I l i I I i I I II i

32、III图9.Context和Resource的类关系图从上图可以看出,Context是把资源的加载、解析和描述工作委托给了ResourcePatternResolver 类来完成,他相当于一个接头人,他把资源的加载、解析和资源的定义整合在一起便于其他组件使用。Core组件中还有很多类似的方式。Ioc容器如何工作前面介绍了 Core组件、Bean组件和Context组件的结构与相互关系,下面这里从使用者角度看一下 他们是如何运行的,以及我们如何让Spring完成各种功能,Spring到底能有那些功能,这些功能是如何得来的,下面介绍。如何创建BeanFactory工厂正如图2描述的那样,Ioc容器

33、实际上就是 Context组件结合其他两个组件共同构建了一个Bean关系网,如何构建这个关系网?构建的入口就在 AbstractApplicationContext 类的refresh 方法中。这个方 法 的代码如下:清单 1.AbstractApplicationContext.refresh1. public void refresh() throws BeansException, IllegalStateException 2.2. synchronized (this.startupShutdownMonitor) 4.3. / Prepare this context for re

34、freshing.6.4. prepareRefresh();8.9./ Tell the subclass to refresh the internal bean factory.10.=obtainFreshBeanFactory();11. ConfigurableListableBeanFactorybeanFactory12.12. / Prepare the bean factory for use in this context.14.13. prepareBeanFactory(beanFactory);16.14. try 18.15. / Allows postproce

35、ssing of the bean factory in context subclasses.20.16. postProcessBeanFactory(beanFactory);22.17. / Invoke factory processors registered as beans in the context.24.18. invokeBeanFactoryPostProcessors(beanFactory);26.19. / Register bean processors that intercept bean crea tion.28.20. registerBea

36、nPostProcessors (beanFactory);30.21. / Initialize message source for this context.32.22. initMessageSource();34.23. / Initialize event multicaster for this context.36.24. initApplicationEventMulticaster();38.25. / Initialize other special beans in specific contex t subclasses.40.26. onRefresh();42.2

37、7. / Check for listener beans and register them.44.28. registerListeners();46.29. / Instantiate all remaining (non-lazy-init) singletons.48.finishBeanFactoryInitialization (beanFactory);50.51./ Last step: publish corresponding event.52.53.finishRefresh();7.catch (BeansException ex) 58.59./

38、 Destroy already created singletons to avoid dangl ing resources60.61.destroyBeans();62.63./ Reset active flag.64.65.cancelRefresh(ex);66.67./ Propagate exception to caller.68.69.throw ex;6.这个方法就是构建整个IOC容器过程的完整的代码,了解了里面的每一行代码基本上就了解大部分 Spring的原理和功能了。这段代码主要包含这样几个步骤:构建BeanFactory,以便于

39、产生所需的演员”注册可能感兴趣的事件创建Bean实例对象触发被监听的事件下面就结合代码分析这几个过程。第二三句就是在创建和配置 BeanFactory。这里是refresh也就是刷新配置,前面介绍了 Context有 可更新的子类,这里正是实现这个功能,当BeanFactory已存在是就更新,如果没有就新创建。下面是更新BeanFactory的方法代码:清单 2. AbstractRefreshableApplicationContext. refreshBeanFactory1. protected final void refreshBeanFactory。throws BeansExce

40、ption 2.if (hasBeanFactory() destroyBeans();closeBeanFactory();try = createBeanFactory ();DefaultListableBeanFactorybeanFactorybeanFactory.setSerializationld(getld(); customizeBeanFactory(beanFactory);loadBeanDefinitions(beanFactory);synchronized (this.beanFactoryMonitor) this.beanFactory= beanFacto

41、ry;catch (IOException ex) throw new ApplicationContextException(I/O error& nbsp;parsing bean definition source for+ getDisplayName (), ex);.0.这个方法实现了明了 BeanFactory的创建过程。注意BeanFactory情况下使用不同的子类这非常关

42、键。BeanFactoryAbstractApplicationContext的抽象方法refreshBeanFactory ,这段代码清楚的说 对象的类型的变化,前 面介绍了他有很多子类,在什么 的原始对象是 DefaultListableBeanFactory ,这个非常关键,因为他设计到后面对这个对象的多种操作,下面看一下这个类的继承层次类图:ViaAi ipv uhl *Lh fllihl *4 3 tiry! 1 LhtijihliNduJiMi * Sb *4*1 * I mH wiVn a tt * tni ii ; Ji*t *Xk htA he 14AJ - A Canfii

43、 pjrwJ .p.il,|U|.Jl.| feH|TrC LIM kTf LihfJiiEttf7i 上 u:_ I. _j t i i I d s w J : i : = .图 10.DefaultListableBeanFactory类继承关系图从这个图中发现除了BeanFactory相关的类外,还发现了与 Bean的register 相关。这在refreshBeanFactory方法中有一行loadBeanDefinitions(beanFactory)将找到答案,这个方法将开始加载、解析Bean的定义,也就是把用户定义的数据结构转化为Ioc容器中的特定数据结构。这个过程可以用下面时序

44、图解释:tr首仙i 首首 :忒 PitthFm til 时曲寸! wf 斗 t mrfcbitT KtSlirlftTpL 弓陽1!; *贰 in1,T育迥母由 卄 wR曲|1: ft-t ii口1. LM血九72/;I、泌二ml- 3 0r7 v JvkJ-wJJh;T图11.创建BeanFactory时序图Bean的解析和登记流程时序图如下:1 3.IXi:I鼻 I i t 2 g.1E1 11 11rE-1品”汕*hi iY& (L krlijifr. IJBLi lli J! q耳fi p_ UuiT*丹帘FmcJm 说.十I盲;ll ffi-K WlriiiTh fl- I i *i

45、石UU叮h”辰7| p IM Jiiv*I-J图12.解析和登记Bean对象时序图创建好BeanFactory后,接下去添加一些 Spring本身需要的一些工具类,这个操作在 AbstractApplicationContext 的 prepareBeanFactory 方法完成。AbstractApplicationContext中接下来的三行代码对Spring的功能扩展性起了至关重要的作用。前两行主要是让你现在可以对已经构建的BeanFactory的配置做修改,后面一行就是让你可以对以后再创建Bean的实例对象时添加一些自定义的操作。所以他们都是扩展了 Spring的功能,所以我们要学习使

46、用 Spring必须对这一部分搞清楚。其中在 invokeBeanFactoryPostProcessors方法中主要是获取实现 BeanFactoryPostProcessor 接口的子类。并执行它的postProcessBeanFactory 方法,这个方法的声明如下:清单 3.BeanFactoryPostProcessor.postProcessBeanFactory1. void postProcessBea nF actory(C on figurableListableBea nF actory bea nF actory)2.3.throws Bean sExcepti on;

47、它的参数是 beanFactory,说明可以对 beanFactory 做修改,这里注意这个beanFactory 是ConfigurableListableBeanFactory 类型的,这也印证了前面介绍的不同BeanFactory所使用的场合不同,这里只能是可配置的BeanFactory,防止一些数据被用户随意修改。registerBeanPostProcessors方法也是可以获取用户定义的实现了BeanPostProcessor接口的子类,并执行把它们注册到BeanFactory对象中的beanPostProcessors 变量中。BeanPostProcessor中声明了两个方法:

48、 postProcessBeforelnitialization、postProcessAfterInitialization分另U用于在 Bean 对象初始化时执行。可以执行用户自定义的操作。后面的几行代码是初始化监听事件和对系统的其他监听者的注册,监听者必须是ApplicationListener的子类。如何创建Bean实例并构建Bean的关系网下面就是Bean的实例化代码,是从finishBeanFactorylnitialization方法开始的。清单 4.AbstractApplicationContext.finishBeanFactorylnitialization1. prot

49、ected void finishBeanFactoryInitialization(2.2. ConfigurableListableBeanFactory beanFactory) . / Stop using the temporary ClassLoader for type matching.8.4. beanFactory.setTempClassLoader(null);3. / Allow for caching all bean definition metadata, not expecting further changes .14.14

50、. beanFactory.freezeConfiguration();5. / Instantiate all remaining (non-lazy-init) singletons.20.16. beanFactory.prelnstantiateSingletons();22.17. 24.从上面代码中可以发现Bean的实例化是在BeanFactory中发生的。preInstantiateSingletons 方法的代码如下:清单 5.DefaultListableBeanFactory.preInstantiateSingletons18. public void

51、 preInstantiateSingletons。throws BeansException 26.19. if (this.logger.islnfoEnabled() 28.20. thiso (Pre- instantiating singletons in + this);30.21. 32.synchronized (this.beanDefinitionMap) for (String beanName : this.beanDefinitionNames) RootBeanDefinitionbd = getMergedLocalBeanDefinition(

52、beanName);if (!bd.isAbstract() & bd.isSingleton()& !bd.isLazylnit() if (isFactoryBean(beanName) final FactoryBean factory =(FactoryBean) getBean(FACTORY_BEAN_PREFIX+ beanName);boolean isEagerInit;if (System.getSecurityManager() != null& factory instanceof SmartFactoryBean) isEagerInit = AccessContro

53、ller .doPrivileged(&nb sp; new PrivilegedAction () &nb sp; public Boolean run() return (SmartFactoryBean) factory).isEagerInit();&nb sp; , getAcce ssControlContext();else isEagerInit = factory instanceof SmartFactoryBean&nb5.sp; & (SmartFactoryBean) factory).isEagerlnit();76.77.if (isEagerIn

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论