Spring技术内幕:深入解析Spring架构与设计原理_第1页
Spring技术内幕:深入解析Spring架构与设计原理_第2页
Spring技术内幕:深入解析Spring架构与设计原理_第3页
Spring技术内幕:深入解析Spring架构与设计原理_第4页
Spring技术内幕:深入解析Spring架构与设计原理_第5页
已阅读5页,还剩144页未读 继续免费阅读

下载本文档

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

文档简介

Spring技术内幕

深入解析Spring架构与设计原理(一)引子

缘起

已经很久没有写帖子了,现在总算是有点时间写些东西,也算是对自己的一个记

录吧。刚刚完成了一个软件产品,从概念到运营都弄了一下,正在推广当中,虽

然还没有能够达到盈亏平衡,但是这个过程,对自己也算是一种历练。先不管结

果如何,好呆走过这么一遭了。

我打算用这个帖子,把自己在这个过程中的一些心得,特别是对Spring新的理

解,记录下来。使用这个帖子的标题,持续下来。

简单来说,自己的软件产品是一个基于互联网的SaaS协同软件平台,操作简单,

支持流程定义,管理和多种客户端-像短信,MSN,智能手机什么的(我这里

就不多做什么广告了),也有一个企业版的版本,使用的技术框架是Hibernate

+Spring+Wicket,下面是Linux和MySQL,还有云计算的平台的使用,以

支持其扩展性,虽然现在还没有可扩展性的需求,但似乎不难从SaaS上,就会

想到云计算,其实,它们真的是天生的一对!

关于云计算启己对这个技术很感兴趣,觉得和开源软件的结合,是很有意思的,

因为它们都有基于服务的基因,在云计算平台的使用上,也有一些初步的实践。

云计算是一个很有意思的话题,但在这里主要是想谈Spring,所以对云计算,

这里就先不多说了,但非常欢迎有兴趣的朋友和一起另外找地方讨论!

回到正题,在我自己的产品中,其中除了Wicket和云计算外,其他都是大家非

常熟知的了,像Hibernate,Spring,MySQL什么的。在这个过程中,发现自己

对一些技术点也有了新的认识,最有体会的是Spring。当然,在这个过程中,

更大的收获是对产品开发整个过程的认识,在这点上,真是一言难尽…••…

回到自己还算了解的Spring,这次我使用的是3.0的代码,所以,有机会也把这

些代码读了几遍,比原来的理解要加深了许多,也发现了不少和2.0代码不同的

地方,以及自己一些对Spring的新的理解,这些,就让我就用这个帖子系列,

给自己总结一下,也算是对自己以前的那个代码分析的帖子做一个新的交代吧。

自己对Spring一点小小的见解

简化Java企业应用的开发,是Spring框架的目标.就是我们熟知的当年的那个

interface21,也亦非吴下阿蒙了,由它演进出来的Spring,以及由它带来的崭

新开发理念,也早已伴随着这个开源框架的广泛应用,而飞入寻常百姓家。与此

同时,伴随着Spring的成熟,开源社区的成长,在Rod.Johnson的领导下,

以Spring为核心的一系列开源软件的产品组合,其脉络也逐渐的清晰和丰富起

来;现在,已经发展成为一个包括软件运行,构建,部署运营,从而涵盖整个

软件服务生命周期的产品族群;同时也成为,在当今主流的软件业态中,一个不

可或缺的重要组成。

在最近完成的VMware公司对Spring的运营者SpringSource公司的收购中,

也让我们又看到了一个,在开源软件中,蕴含着的巨大商业价值,以及又一次

基于开源模式的商业成功;也让我们看到,Spring为自己设计的未来定位,它

与云计算的融合趋势,以及,努力成为在云计算业态中,PaaS(PlatformAsa

Service)服务有力竞争者的战略设想;由此,可以想象,在云计算这个全新的

计算时代中,如何秉承Spring的一贯风格,为云计算应用的开发,提供高可

靠,高可用,高可扩展,高性能的应用平台,对Spring团队来说,是一个面临

的全新挑战;在这个领域中的雄心和今后的作为,那就让我们一起拭目以待吧。

这里也有点凑巧了,正好Spring和云计算都是自己喜欢的东西,说不定以后,

我还能够在这两者的结合上再写些东西呢。

作为一个庞大的体系,Spring在Java企业应用中,和我们熟悉的企业应用服务

器一样,比如我们熟知的其他产品,像Weblogic,Websphere,JBoss,.NET这些

等等,其定位和目的,都在于希望能够起到一个企业应用资源的集成管理,以

及为应用开发提供平台支持的作用,这和我们熟知的,像UNIX和Windows这

样传统意义上的操作系统,在传统的计算系统中,起到的作用非常的类似。只

不过按照个人的理解,它们不同在于,我们熟知的传统操作系统关心的是存储,

计算,通信,外围设备这些物理资源的管理,并在管理这些资源的基础上,为

应用程序提供一个统一平台和服务接口;而像Spring这样的应用平台,它们关

心的是在Java企业应用中,对包括那些像Web应用,数据持久化,事务处理,

消息中间件,分布式计算等等这些,为企业应用服务的抽象资源的统一管理,并

在此基础上,为应用提供一个基于POJO的开发环境。尽管各自面向的资源,

管理的对象,支持的应用以及使用的场景不同,但这两者在整个系统中的定位,

却依然有着可以类比和相互参考的地方,从某种意义上看,它们都起到一个资

源协调,平台支持,以及服务集成的作用。

所以我觉得可以使用,我们看待传统操作系统的方法和一些基本观念,来对

Spring进行系统分析以及对Spring进行层次划分,这样可能更加容易理解,

同时,所以,个人感觉,仿照传统操作系统的眼光,把对Spring框架的实现,

划分为核心,组件和应用这三个基本的层次,来理解Spring框架是不错的一

个方法,就算是众所周知的"三段论"的应用吧。不知道这种分析方法,是不是

太庸俗,但我自己还是觉得挺受用的,呵呵,谁叫我是个俗人呢!

今天先写一些,就算是起个头吧,明天继续!写写IOC/AOP的一些具体东西。

深入解析Spring架构与设计原理(一)IOC实现原理

IOC的基础

下面我们从IOC/AOP开始,它们是Spring平台实现的核心部分;虽然,我们

一开始大多只是在这个层面上,做一些配置和外部特性的使用工作,但对这两

个核心模块工作原理和运作机制的理解,对深入理解Spring平台,却是至关重

要的;因为,它们同时也是Spring其他模块实现的基础。从Spring要做到的

目标,也就是从简化JavaEE开发的出发点来看,简单的来说,它是通过对POJO

开发的支持,来具体实现的;具体的说,Spring通过为应用开发提供基于POJO

的开发模式,把应用开发和复杂的JavaEE服务,实现解耦,并通过提高单元

测试的覆盖率,从而有效的提高整个应用的开发质量。这样一来,实际上,就需

要把为POJO提供支持的,各种JavaEE服务支持抽象到应用平台中去,去封装

起来;而这种封装功能的实现,在Spring中,就是由IOC容器以及AOP来具

体提供的,这两个模块,在很大程度上,体现了Spring作为应用开发平台的

核心价值。它们的实现,是RodJohnson在他的另一本著作《Expert

One-on-OneJ2EEDevelopmentwithoutEJB》中,所提到WithoutEJB设

计思想的体现;同时也深刻的体现了Spring背后的设计理念。

从更深一点的技术层面上来看,因为Spring是一个基于Java语言的应用平台,

如果我们能够对Java计算模型,比如像JVM虚拟机实现技术的基本原理有一

些了解,会让我们对Spring实现的理解,更加的深入,这些JVM虚拟机的特

性使用,包括像反射机制,代理类,字节码技术等等。它们都是在Spring实

现中,涉及到的一些Java计算环境的底层技术;尽管对应用开发人员来说,可

能不会直接去涉及这些JVM虚拟机底层实现的工作,但是了解这些背景知识,

或多或少,对我们了解整个Spring平台的应用背景有很大的帮助;打个比方来

说,就像我们在大学中,学习的那些关于计算机组织和系统方面的基本知识,

比如像数字电路,计算机组成原理,汇编语言,操作系统等等这些基本课程的学

习。虽然,坦率的来说,对我们这些大多数课程的学习者,在以后的工作中,

可能并没有太多的机会,直接从事这么如此底层的技术开发工作;但具备这些知

识背景,为我们深入理解基于这些基础技术构架起来的应用系统,毫无疑问,是

不可缺少的。随着JVM虚拟机技术的发展,可以设想到的是,更多虚拟机级别

的基本特性,将会持续的被应用平台开发者所关注和采用,这也是我们在学习平

台实现的过程中,非常值得注意的一点,因为这些底层技术实现,毫无疑问,

会对Spring应用平台的开发路线,产品策略产生重大的影响。同时,在使用

Spring作为应用平台的时候,如果需要更深层次的开发和性能调优,这些底层

的知识,也是我们知识库中不可缺少的部分。有了这些底层知识,理解整个系统,

想来就应该障碍不大了。

IOC的一点认识

MSpringIOC的理解离不开对依赖反转模式的理解,我们知道,关于如何反转

对依赖的控制,把控制权从具体业务对象手中转交到平台或者框架中,是解决面

向对象系统设计复杂性和提高面向对象系统可测试性的一个有效的解决方案。

这个问题触发了IoC设计模式的发展,是IoC容器要解决的核心问题。同时,

也是产品化的IoC容器出现的推动力。而我觉得Spring的IoC容器,就是一个

开源的实现依赖反转模式的产品。

那具体什么是IoC容器呢?它在Spring框架中到底长什么样?说了这么多,其

实对IoC容器的使用者来说,我们常常接触到的BeanFactory和

Applicationcontext都可以看成是容器的具体表现形式。这些就是IoC容器,

或者说在Spring中提IoC容器,从实现来说,指的是一个容器系列。这也就

是说,我们通常所说的IoC容器,如果深入到Spring的实现去看,会发现IoC

容器实际上代表着一系列功能各异的容器产品。只是容器的功能有大有小,有

各自的特点。打个比方来说,就像是百货商店里出售的商品,我们举水桶为例子,

在商店中出售的水桶有大有小;制作材料也各不相同,有金属的,有塑料的等

等,总之是各式各样,但只要能装水,具备水桶的基本特性,那就可以作为水桶

来出售来让用户使用。这在Spring中也是一样,它有各式各样的IoC容器的实

现供用户选择和使用;使用什么样的容器完全取决于用户的需要,但在使用之前

如果能够了解容器的基本情况,那会对容器的使用是非常有帮助的;就像我们

在购买商品时进行的对商品的考察和挑选那样。

我们从最基本的XmlBeanFactory看起,它是容器系列的最底层实现,这个容

器的实现与我们在Spring应用中用到的那些上下文相比,有一个非常明显的

特点,它只提供了最基本的IoC容器的功能。从它的名字中可以看出,这个IoC

容器可以读取以XML形式定义的BeanDefinition.理解这一点有助于我们理

解Applicationcontext与基本的BeanFactory之间的区别和联系。我们可以

认为直接的BeanFactory实现是IoC容器的基本形式,而各种

Applicationcontext的实现是IoC容器的高级表现形式。

仔细阅读XmlBeanFactory的源码,在一开始的注释里面已经对

XmlBeanFactory的功能做了简要的说明,从代码的注释还可以看到,这是Rod

Johnson在2001年就写下的代码,可见这个类应该是Spring的元老类了。它

是继承DefaultListableBeanFactory这个类的,这个

DefaultListableBeanFactory就是一个很值得注意的容器!

Java代码

1.publicclassXmlBeanFactoryextendsDefaultListableBeanFactory{

2.privatefinalXmlBeanDefinitionReaderreader=newXmlBeanD

efinitionReader(this);

3.publicXmlBeanFactory(Resourceresource)throwsBeansExcept

ion{

4.this(resource,null);

5.)

6.publicXmlBeanFactory(Resourceresource,BeanFactoryparent

BeanFactory)throwsBeansException{

7.super(parentBeanFactory);

8.this.reader.loadBeanDefinitions(resource);

9.)

10.}

publicclassXmlBeanFactoryextendsDefaultListableBeanFactory{

privatefinalXmlBeanDefinitionReaderreader=new

XmlBeanDefinitionReader(this);

publicXmlBeanFactory(Resourceresource)throws

BeansException{

this(resource,null);

)

publicXmlBeanFactory(Resourceresource,BeanFactory

parentBeanFactory)throwsBeansException{

super(parentBeanFactory);

this.reader.loadBeanDefinitions(resource);

)

)

XmlBeanFactory的功能是建立在DefaultListableBeanFactory这个基本容器

的基础上的在这个基本容器的基础上实现了其他诸如XML读取的附加功能。

对于这些功能的实现原理,看一看XmlBeanFactory的代码实现就能很容易地

理解。在如下的代码中可以看到,在XmlBeanFactory构造方法中需要得到

Resource对象。对XmlBeanDefinitionReader对象的初始化,以及使用这个

这个对象来完成loadBeanDefinitions的调用,就是这个调用启动了从

Resource中载入BeanDefinitions的过程,这个loadBeanDefinitions同时

也是IoC容器初始化的重要组成部分。

简单来说,IoC容器的初始化包括BeanDefinition的Resouce定位、载入和注

册这三个基本的过程。我觉得重点是在载入和对BeanDefinition做解析的这个

过程。可以从DefaultListableBeanFactory来入手看看IoC容器是怎样完成

BeanDefinition载入的。在refresh调用完成以后,可以看到loadDefinition

的调用:

Java代码

1.publicabstractclassAbstractXmlApplicationContextextendsAbst

ractRefreshableConfigApplicationContext{

2.publicAbstractXmlApplicationContextO{

3.)

4.publicAbstractXmlApplicationContext(ApplicationContextpare

nt){

5.super(parent);

6.)

7.〃这里是实现loadBeanDefinitions的地方

8.protectedvoidloadBeanDefinitions(DefaultListableBeanFactory

beanFactory)throwslOException{

9.//CreateanewXmlBeanDefinitionReaderforthegivenBean

Factory.

10.//创建XmlBeanDefinitionReader,并通过回调设置

到BeanFactory中去,创建BeanFactory的使用的也

DefaultListableBeanFactoryo

11.XmlBeanDefinitionReaderbeanDefinitionReader=newXmlB

eanDefinitionReader(beanFactory);

12.

13.//Configurethebeandefinitionreaderwiththiscontext's

14.//resourceloadingenvironment.

15.〃这里设置XmlBeanDefinitionReader,为

XmlBeanDefinitionReader酉己置ResourceLoader,因为

DefaultResourceLoader是父类,所以this可以直接被使用

16.beanDefinitionReader.setResourceLoader(this);

17.beanDefinitionReader.setEntityResolver(newResourceEntityR

esolver(this));

18.

19.//Allowasubclasstoprovidecustominitializationoftherea

der,

20.//thenproceedwithactuallyloadingthebeandefinitions.

21.〃这是启动Bean定义信息载入的过程

22.initBeanDefinitionReader(beanDefinitionReader);

23.loadBeanDefinitions(beanDefinitionReader);

24.)

25.

26.protectedvoidinitBeanDefinitionReader(XmlBeanDefinitionRea

derbeanDefinitionReader){

27.}

publicabstractclassAbstractXmlApplicationContextextends

AbstractRefreshableConfigApplicationContext{

publicAbstractXmlApplicationContextQ{

)

publicAbstractXmlApplicationContext(ApplicationContext

parent){

super(parent);

)

〃这里是实现loadBeanDefinitions的地方

protectedvoidloadBeanDefinitions(DefaultListableBeanFactory

beanFactory)throwslOException{

//CreateanewXmlBeanDefinitionReaderforthegiven

BeanFactory.

//创建XmlBeanDefinitionReader,并通过回调设置到

BeanFactory中去,创建BeanFactory的使用的也是

DefaultListableBeanFactoryo

XmlBeanDefinitionReaderbeanDefinitionReader=new

XmlBeanDefinitionReader(beanFactory);

//Configurethebeandefinitionreaderwiththis

context's

//resourceloadingenvironment.

〃这里设置XmlBeanDefinitionReader,为

XmlBeanDefinitionReader酉己置ResourceLoader,因为

DefaultResourceLoader是父类,所以this可以直接被使用

beanDefinitionReader.setResourceLoader(this);

beanDefinitionReader.setEntityResolver(new

ResourceEntityResolver(this));

//Allowasubclasstoprovidecustominitializationofthe

reader,

//thenproceedwithactuallyloadingthebean

definitions.

//这是启动Bean定义信息载入的过程

initBeanDefinitionReader(beanDefinitionReader);

loadBeanDefinitions(beanDefinitionReader);

)

protectedvoid

initBeanDefinitionReader(XmlBeanDefinitionReader

beanDefinitionReader){

)

这里使用XmlBeanDefinitionReader来载入BeanDefinition至!]容器中,如以

下代码清单所示:

Java代码

1.〃这里是调用的入口。

2.publicintloadBeanDefinitions(Resourceresource)throwsBean

DefinitionStoreException{

3.returnloadBeanDefinitions(newEncodedResource(resource))

/

4.)

5.〃这里是载入XML形式的BeanDefinition的地方。

6.publicintloadBeanDefinitions(EncodedResourceencodedReso

urce)throwsBeanDefinitionStoreException{

7.Assert.notNull(encodedResource,"EncodedResourcemustn

otbenull");

8.if(logger.isInfoEnabled()){

9.("LoadingXMLbeandefinitionsfrom"+encod

edResource.getResource());

10.}

11.

12.Set<EncodedResource>currentResources=this.resourcesC

urrentlyBeingLoaded.get();

13.if(currentResources==null){

14.currentResources=newHashSet<EncodedResource>(4);

15.this.resourcesCurrentlyBeingLoaded.set(currentResources);

16.}

17.if(!currentResources.add(encodedResource)){

18.thrownewBeanDefinitionStoreException(

19."Detectedrecursiveloadingof"+encodedResource

+"-checkyourimportdefinitions!");

20.)

21.〃这里得到XML文件,并得到10的Inputsource准备进行读取。

22.try{

23.Inputstreaminputstream=encodedResource.getResourc

e().getInputStream();

24.try{

25.InputSourceinputSource=newInputSource(inputStrea

m);

26.if(encodedResource.getEncodingO!=null){

27.inputSource.setEncoding(encodedResource.getEncod

ingO);

28.}

29.returndoLoadBeanDefinitions(inputSource,encodedRe

source.getResource());

30.)

31.finally{

32.inputStream.closeO;

33.)

34.)

35.catch(lOExceptionex){

36.thrownewBeanDefinitionStoreException(

37."lOExceptionparsingXMLdocumentfrom"+encod

edResource.getResource(),ex);

38.)

39.finally{

40.currentResources.remove(encodedResource);

41.if(currentResources.isEmptyO){

42.this.resourcesCurrentlyBeingLoaded.set(null);

43.)

44.)

45.}

46.〃具体的读取过程可以在doLoadBeanDefinitions方法中找到:

47.〃这是从特定的XML文件中实际载入BeanDefinition的地方

48.protectedintdoLoadBeanDefinitions(InputSourceinputSource,

Resourceresource)

49.throwsBeanDefinitionStoreException{

50.try{

51.intvalidationMode=getValidationModeForResource(reso

urce);

52.〃这里取得XML文件的Document对象,这个解析过程是

由documentLoader完成的,这个documentLoader是

DefaultDocumentLoader,在定义documentLoader的地方创建

53.Documentdoc=this.documentLoader.loadDocument(

54.inputSource,getEntityResolver(),this.errorHandler,va

lidationMode,isNamespaceAwareO);

55.〃这里启动的是对BeanDefinition解析的详细过程,这个解析会

使用到Spring的Bean配置规则,是我们下面需要详细关注的地方。

56.returnregisterBeanDefinitions(doc,resource);

57.)

58.catch(BeanDefinitionStoreExceptionex){

59.throwex;

60.)

61.catch(SAXParseExceptionex){

62.thrownewXmlBeanDefinitionStoreException(resource.get

DescriptionO,

63."Line"+ex.getLineNumber()+"inXMLdocumentfr

om"+resource+"isinvalid",ex);

64.)

65.catch(SAXExceptionex){

66.thrownewXmlBeanDefinitionStoreException(resource.get

DescriptionO,

67."XMLdocumentfrom"+resource+"isinvalid",ex);

68.)

69.catch(ParserConfigurationExceptionex){

70.thrownewBeanDefinitionStoreException(resource.getDes

criptionO,

71."ParserconfigurationexceptionparsingXMLfrom"

+resource,ex);

72.)

73.catch(lOExceptionex){

74.thrownewBeanDefinitionStoreException(resource.getDes

criptionO,

75."lOExceptionparsingXMLdocumentfrom"+resour

ce,ex);

76.)

77.catch(Throwableex){

78.thrownewBeanDefinitionStoreException(resource.getDes

criptionO,

79."UnexpectedexceptionparsingXMLdocumentfrom

"+resource,ex);

80.)

81.)

〃这里是调用的入口。

publicintloadBeanDefinitions(Resourceresource)throws

BeanDefinitionStoreException{

returnloadBeanDefinitions(new

EncodedResource(resource));

)

〃这里是载入XML形式的BeanDefinition的地方。

publicintloadBeanDefinitions(EncodedResource

encodedResource)throwsBeanDefinitionStoreException{

Assert.notNull(encodedResource,"EncodedResource

mustnotbenull");

if(logger.isInfoEnabledO){

(nLoadingXMLbeandefinitionsfrom

"+encodedResource.getResource());

)

Set<EncodedResource>currentResources=

this.resourcesCurrentlyBeingLoaded.get();

if(currentResources==null){

currentResources=new

HashSet<EncodedResource>(4);

this.resourcesCurrentlyBeingLoaded.set(currentResources);

)

if(!currentResources.add(encodedResource)){

thrownewBeanDefinitionStoreException(

"Detectedrecursiveloadingof"

+encodedResource+--checkyourimportdefinitions!");

)

〃这里得到XML文件,并得到10的Inputsource准备进行读

取。

try(

Inputstreaminputstream=

encodedResource.getResource().getInputStream();

try(

InputSourceinputSource=new

InputSource(inputStream);

if(encodedResource.getEncodingO!=

null){

inputSource.setEncoding(encodedResource.getEncodingO);

)

return

doLoadBeanDefinitions(inputSource,encodedResource.getResourceO);

)

finally{

inputStream.closeO;

)

)

catch(lOExceptionex){

thrownewBeanDefinitionStoreException(

"lOExceptionparsingXML

documentfrom"+encodedResource.getResource(),ex);

)

finally{

currentResources.remove(encodedResource);

if(currentResources.isEmptyO){

this.resourcesCurrentlyBeingLoaded.set(null);

)

)

)

〃具体的读取过程可以在doLoadBeanDefinitions方法中找到:

〃这是从特定的XML文件中实际载入BeanDefinition的地方

protectedintdoLoadBeanDefinitions(InputSourceinputSource,

Resourceresource)

throwsBeanDefinitionStoreException{

try{

intvalidationMode=

getValidationModeForResource(resource);

〃这里取得XML文件的Document对象,这个解析

过程是由documentLoader完成的,这个documentLoader是

DefaultDocumentLoader,在定义documentLoader的地方创建

Documentdoc=

this.documentLoader.loadDocument(

inputSource,getEntityResolverO,

this.errorHandler,validationMode,isNamespaceAwareO);

〃这里启动的是对BeanDefinition解析的详细过程,

这个解析会使用到Spring的Bean配置规则是我们下面需要详细关注的地方。

returnregisterBeanDefinitions(doc,resource);

)

catch(BeanDefinitionStoreExceptionex){

throwex;

)

catch(SAXParseExceptionex){

thrownew

XmlBeanDefinitionStoreException(resource.getDescription(),

"Line"+ex.getLineNumber()+

inXMLdocumentfrom"+resource+"isinvalid",ex);

)

catch(SAXExceptionex){

thrownew

XmlBeanDefinitionStoreException(resource.getDescription(),

"XMLdocumentfrom"+

resource+"isinvalid",ex);

)

catch(ParserConfigurationExceptionex){

thrownew

BeanDefinitionStoreException(resource.getDescription(),

"Parserconfigurationexception

parsingXMLfrom"+resource,ex);

)

catch(lOExceptionex){

thrownew

BeanDefinitionStoreException(resource.getDescription(),

"lOExceptionparsingXML

documentfrom"+resource,ex);

)

catch(Throwableex){

thrownew

BeanDefinitionStoreException(resource.getDescription(),

"Unexpectedexceptionparsing

XMLdocumentfrom"+resource,ex);

)

)

关于具体的SpringBeanDefinition的解析,是在

BeanDefinitionParserDelegate中完成的。这个类里包含了各种SpringBean

定义规则的处理,感兴趣的同学可以仔细研究。我们举一个例子来分析这个处理

过程比如我们最熟悉的对Bean元素的处理是怎样完成的也就是我们在XML

定义文件中出现的<bean></bean>这个最常见的元素信息是怎样被处理的。

在这里,我们会看到那些熟悉的BeanDefinition定义的处理,比如id、name、

aliase等属性元素。把这些元素的值从XML文件相应的元素的属性中读取出来

以后,会被设置到生成的BeanDefinitionHolder中去。这些属性的解析还是

比较简单的。对于其他元素配置的解析,比如各种Bean的属性配置,通过一

个较为复杂的解析过程,这个过程是由parseBeanDefinitionElement来完成的。

解析完成以后,会把解析结果放到BeanDefinition对象中并设置到

BeanDefinitionHolder中去,如以下清单所示:

Java代码

1.publicBeanDefinitionHolderparseBeanDefinition日ement(日emen

tele,BeanDefinitioncontainingBean){

2.〃这里取得在<bean>元素中定义的id、name和aliase属性的值

3.Stringid=ele.getAttribute(ID_ATTRIBUTE);

4.StringnameAttr=ele.getAttribute(NAME_ATTRIBUTE);

5.

6.List<String>aliases=newArrayList<String>();

7.if(Stringlltils.hasLength(nameAttr)){

8.String[]nameArr=Stringlltils.tokenizeToStringArray(nam

eAttr,BEAN_NAME_DELIMITERS);

9.aliases.addAII(Arrays.asList(nameArr));

10.)

11.

12.StringbeanName=id;

13.if(!Stringlltils.hasText(beanName)&&!aliases.isEmpty()){

14.beanName=aliases.remove(O);

15.if(logger.isDebugEnabled()){

16.logger.debug("NoXML'id'specified-using,n+beanN

ame+

17.asbeannameand"+aliases+"asaliases");

18.)

19.)

20.

21.if(containingBean==null){

22.checkNamellniqueness(beanName,aliases,ele);

23.)

24.

25.〃这个方法会引发对bean元素的详细解析

26.AbstractBeanDefinitionbeanDefinition=parseBeanDefinition日e

ment(ele,beanName,containingBean);

27.if(beanDefinition!=null){

28.if(!Stringlltils.hasText(beanName)){

29.try{

30.if(containingBean!=null){

31.beanName=BeanDefinitionReaderlltils.generateB

eanName(

32.beanDefinition,this.readerContext.getRegistry

0,true);

33.)

34.else{

35.beanName=this.readerContext.generateBeanNa

me(beanDefinition);

36.//Registeranaliasfortheplainbeanclassname,if

st川possible,

37.//ifthegeneratorreturnedtheclassnameplusas

uffix.

38.//ThisisexpectedforSpring1.2/2.0backwardsco

mpatibility.

39.StringbeanClassName=beanDefinition.getBeanCI

assName();

40.if(beanClassName!=null&&

41.beanName.startsWith(beanClassName)&&b

eanName.lengthQ>beanClassName.length()&&

42.!this.readerContext.getRegistry().isBeanNameI

nllse(beanClassName)){

43.aliases.add(beanClassName);

44.)

45.)

46.if(logger.isDebugEnabledO){

47.logger.debug("NeitherXML'id'nor'name'specifie

d-

48."usinggeneratedbeanname["+beanName

+T);

49.)

50.}

51.catch(Exceptionex){

52.error(ex.getMessage(),ele);

53.returnnull;

54.)

55.)

56.String[]aliasesArray=StringUtils.toStringArray(aliases);

57.returnnewBeanDefinitionHolder(beanDefinition,beanNa

me,aliasesArray);

58.)

59.

60.returnnull;

61.)

publicBeanDefinitionHolderparseBeanDefinition日ement(日ementele,

BeanDefinitioncontainingBean){

〃这里取得在<bean>元素中定义的id、name和aliase属性

的值

Stringid=ele.getAttribute(ID_ATTRIBUTE);

StringnameAttr=ele.getAttribute(NAME_ATTRIBUTE);

List<String>aliases=newArrayList<String>();

if(StringUtils.hasLength(nameAttr)){

String[]nameArr=

Stringlltils.tokenizeToStringArray(nameAttr,BEAN_NAME_DELIMITERS);

aliases.addAII(Arrays.asList(nameArr));

)

StringbeanName=id;

if(!Stringlltils.hasText(beanName)&&!aliases.isEmpty())

(

beanName=aliases.remove(O);

if(logger.isDebugEnabledO){

logger.debug(nNoXML'id'specified-

using+beanName+

asbeannameand"+

aliases+"asaliases");

)

)

if(containingBean==null){

checkNamellniqueness(beanName,aliases,ele);

)

〃这个方法会引发对bean元素的详细解析

AbstractBeanDefinitionbeanDefinition=

parseBeanDefinitionElement(ele,beanName,containingBean);

if(beanDefinition!=null){

if(!Stringlltils.hasText(beanName)){

try(

if(containingBean!=null){

beanName=

BeanDefinitionReaderlltils.generateBeanName(

beanDefinition,this.readerContext.getRegistryO,true);

)

else{

beanName=

this.readerContext.generateBeanName(beanDefinition);

//Registeranaliasfor

theplainbeanclassname,ifstillpossible,

//ifthegenerator

returnedtheclassnameplusasuffix.

//Thisisexpectedfor

Spring1.2/2.0backwardscompatibility.

StringbeanClassName

=beanDefinition.getBeanClassName();

if(beanClassName!=

null&&

beanName.startsWith(beanClassName)&&beanName.length()>

beanClassName.length()&&

!this.readerContext.getRegistry().isBeanNameInllse(beanClassN

ame)){

aliases.add(beanClassName);

)

)

if(logger.isDebugEnabled()){

温馨提示

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

评论

0/150

提交评论