//www.springframework.org/schema/beans"
xmlns:
xsi="http:
//www.w3.org/2001/XMLSchema-instance"
xmlns:
context="http:
//www.springframework.org/schema/context"
xsi:
schemaLocation="http:
//www.springframework.org/schema/context
http:
//www.springframework.org/schema/context/spring-context-3.2.xsd
http:
//www.springframework.org/schema/beans
http:
//www.springframework.org/schema/beans/spring-beans-3.2.xsd>
清单2展示在XML配置文件中引入命名空间的配置范例。
图1.XML命名空间及其handler定义(查看大图)
展开Spring的依赖jar文件,可以看到Spring各个模块对应的jar包都包含一个META-INF目录,如果使用了命名空间,则该目录包含了spring.schemas和spring.handlers两个文件,如图1所示。
然后Spring代码通过Properties工具类扫描project的classpath以及其使用的所有依赖包中META-INF目录来得到对应参数值供后续使用。
PropertiesLoaderUtils.loadAllProperties(“META-INF/spring.schemas”, this.classLoader);
PropertiesLoaderUtils.loadAllProperties(“META-INF/spring.handlers”, this.classLoader);
清单3.JAXP方式解析XML文件为Java对象
protectedintdoLoadBeanDefinitions(InputSourceinputSource,Resourceresource)
throwsBeanDefinitionStoreException{
try{
intvalidationMode=getValidationModeForResource(resource);
//使用JAXP方式,将XML配置文件解析为Java对象。
Documentdoc=this.documentLoader.loadDocument(inputSource,
getEntityResolver(),this.errorHandler,
validationMode,isNamespaceAware());
returnregisterBeanDefinitions(doc,resource);
}
清单3表示Spring源码会创建一些必须的属性或对象,读入配置文件(通常为XML文件),使用JAXP方式将XML元素转换为Java对象(Documentdoc)。
这样Spring对XML配置文件的处理,都可以看作对Java对象的处理。
图2.XML配置文件解析预处理顺序图(查看大图)
图2展示Spring框架如何根据XML配置文件,创建辅助类,从而实现对用户自定义的Bean解析的过程。
详细分析如下:
1.Spring容器在Servlet容器启动后,经过一系列的配置和处理到达如下步骤;
2.调用AbstractApplicationContext对象的refreshBeanFactory();方法。
在这个方法里,将会完成后面所有解析处理。
3.步骤2首先创建一个DefaultListableBeanFactory对象,该对象的类图如图3 所示。
这是Spring框架的核心类,Spring的Bean解析和实例化以及后续的使用都跟该类有非常密切的关系。
从类图右上角部分可知,该类实现了BeanFactory及其几个子接口,这里定义了DefaultListableBeanFactory具有的业务接口(如getBean(…)等)。
而图的左边的类图展示了DefaultListableBeanFactory类的具体业务实现。
图3.DefaultListableBeanFactory类图(查看大图)
4.调用XmlWebApplicationContext对象的loadBeanDefinitions方法,其参数为步骤3创建的beanFactory.这个方法定义了XmlBeanDefinitionReader对象beanDefinitionReader并设置了其属性(如DocumentLoader,EntityResolver等)用于XML文件的解析。
XmlWebApplicationContext对象还负责设置XML配置文件名,默认为/WEB-INF/applicationContext.xml。
如果是开发人员定义的配置文件,则可能为多个。
5.该步骤根据步骤4定义的配置文件名(一个或多个),调用beanDefinitionReader的loadBeanDefinitions方法循环解析每个配置文件,传入的参数为配置文件名。
6.步骤5的beanDefinitionReader会通过JAXP方式解析XML配置文件为Document对象doc,Spring框架对XML配置文件的处理即转化为对Java对象(Document)的处理。
7.步骤4中beanDefinitionReader会创建两个对象:
DefaultBeanDefinitionDocumentReader对象documentReader和XmlReaderContext对象readerContext.DefaultBeanDefinitionDocumentReader的属性如清单4:
清单4.DocumentReader属性清单
publicclassDefaultBeanDefinitionDocumentReader
implementsBeanDefinitionDocumentReader{
publicstaticfinalStringBEAN_ELEMENT=BeanDefinitionParserDelegate.BEAN_ELEMENT;
publicstaticfinalStringNESTED_BEANS_ELEMENT="beans";
publicstaticfinalStringALIAS_ELEMENT="alias";
publicstaticfinalStringNAME_ATTRIBUTE="name";
publicstaticfinalStringALIAS_ATTRIBUTE="alias";
publicstaticfinalStringIMPORT_ELEMENT="import";
publicstaticfinalStringRESOURCE_ATTRIBUTE="resource";
/**@seeorg.springframework.context.annotation.Profile*/
publicstaticfinalStringPROFILE_ATTRIBUTE="profile";
protectedfinalLoglogger=LogFactory.getLog(getClass());
privateXmlReaderContextreaderContext;
privateEnvironmentenvironment;
privateBeanDefinitionParserDelegatedelegate;
从上述清单以及XML配置对比可知,该对象定义了元素可配置文件。
其第
一个属性即为每个Bean的配置元素。
readerContext对象定义了一些如resource,eventListener和
namespaceHandlerResolver等上下文信息。
通过这些属性,Spring框架获得需要解析的XML文件,命名空间解析辅助类以及特定事件的监听器等。
8.以步骤6和7创建的doc和readerContext为参数,调用documentReader对象的registerBeanDefinitions方法。
9.步骤8会创建一个工具类BeanDefinitionParserDelegate,其部分属性如清单5。
清单5.BeanDefinitionParserDelegate属性清单
publicclassBeanDefinitionParserDelegate{
...
publicstaticfinalStringTRUE_VALUE="true";
publicstaticfinalStringFALSE_VALUE="false";
publicstaticfinalStringDEFAULT_VALUE="default";
publicstaticfinalStringDESCRIPTION_ELEMENT="description";
publicstaticfinalStringAUTOWIRE_NO_VALUE="no";
publicstaticfinalStringAUTOWIRE_BY_NAME_VALUE="byName";
publicstaticfinalStringAUTOWIRE_BY_TYPE_VALUE="byType";
publicstaticfinalStringAUTOWIRE_CONSTRUCTOR_VALUE="constructor";
publicstaticfinalStringAUTOWIRE_AUTODETECT_VALUE="autodetect";
publicstaticfinalStringDEPENDENCY_CHECK_ALL_ATTRIBUTE_VALUE="all";
publicstaticfinalStringDEPENDENCY_CHECK_SIMPLE_ATTRIBUTE_VALUE="simple";
publicstaticfinalStringDEPENDENCY_CHECK_OBJECTS_ATTRIBUTE_VALUE="objects";
publicstaticfinalStringNAME_ATTRIBUTE="name";
publicstaticfinalStringBEAN_ELEMENT="bean";
publicstaticfinalStringMETA_ELEMENT="meta";
publicstaticfinalStringID_ATTRIBUTE="id";
publicstaticfinalStringPARENT_ATTRIBUTE="parent";
publicstaticfinalStringCLASS_ATTRIBUTE="class";
publicstaticfinalStringABSTRACT_ATTRIBUTE="abstract";
publicstaticfinalStringSCOPE_ATTRIBUTE="scope";
publicstaticfinalStringSINGLETON_ATTRIBUTE="singleton";
publicstaticfinalStringLAZY_INIT_ATTRIBUTE="lazy-init";
publicstaticfinalStringAUTOWIRE_ATTRIBUTE="autowire";
publicstaticfinalStringAUTOWIRE_CANDIDATE_ATTRIBUTE="autowire-candidate";
publicstaticfinalStringPRIMARY_ATTRIBUTE="primary";
publicstaticfinalStringDEPENDENCY_CHECK_ATTRIBUTE="dependency-check";
publicstaticfinalStringDEPENDS_ON_ATTRIBUTE="depends-on";
publicstaticfinalStringINIT_METHOD_ATTRIBUTE="init-method";
publicstaticfinalStringDESTROY_METHOD_ATTRIBUTE="destroy-method";
publicstaticfinalStringFACTORY_METHOD_ATTRIBUTE="factory-method";
publicstaticfinalStringFACTORY_BEAN_ATTRIBUTE="factory-bean";
publicstaticfinalStringCONSTRUCTOR_ARG_ELEMENT="constructor-arg";
publicstaticfinalStringINDEX_ATTRIBUTE="index";
publicstaticfinalStringTYPE_ATTRIBUTE="type";
publicstaticfinalStringVALUE_TYPE_ATTRIBUTE="value-type";
publicstaticfinalStringKEY_TYPE_ATTRIBUTE="key-type";
publicstaticfinalStringPROPERTY_ELEMENT="property";
publicstaticfinalStringREF_ATTRIBUTE="ref";
publicstaticfinalStringVALUE_ATTRIBUTE="value";
publicstaticfinalStringLOOKUP_METHOD_ELEMENT="lookup-method";
publicstaticfinalStringREPLACED_METHOD_ELEMENT="replaced-method";
publicstaticfinalStringREPLACER_ATTRIBUTE="replacer";
publicstaticfinalStringARG_TYPE_ELEMENT="arg-type";
publicstaticfinalStringREF_ELEMENT="ref";
...
publicstaticfinalStringDEFAULT_LAZY_INIT_ATTRIBUTE="default-lazy-init";
publicstaticfinalStringDEFAULT_MERGE_ATTRIBUTE="default-merge";
publicstaticfinalStringDEFAULT_AUTOWIRE_ATTRIBUTE="default-autowire";
publicstaticfinalStringDEFAULT_DEPENDENCY_CHECK_ATTRIBUTE=
"default-dependency-check";
publicstaticfinalStringDEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE=
"default-autowire-candidates";
publicstaticfinalStringDEFAULT_INIT_METHOD_ATTRIBUTE=
"default-init-method";
publicstaticfinalStringDEFAULT_DESTROY_METHOD_ATTRIBUTE=
"default-destroy-method";
...
privatefinalXmlR