一.需求
探討Spring 配置文件 bean.xml 中元素是如何被解析的
二.xml構(gòu)成劃分
1.dispatcher-servlet.xml案例
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd">
<context:component-scan base-package="com.beijing"
<bean id="student" class="com.beijing.Student">
</beans>
2.dispatcher-servlet.xml構(gòu)成
2.1schema
schema即beans 標(biāo)簽屬性, 大致分為兩部分 xmlns, xsi:schemaLocation
- xml namespace,xmlns作用有二
- 定義與下文xsi:schemaLoaction的關(guān)聯(lián)關(guān)系胚宦,整體結(jié)構(gòu):
xmlns:mvc="key"
xsi:schemaLocation="key keyLocation" - 定義下文標(biāo)簽的使用方式钝诚,整體結(jié)構(gòu):
xmlns:context="key"
<context: component-scan="">
- 定義與下文xsi:schemaLoaction的關(guān)聯(lián)關(guān)系胚宦,整體結(jié)構(gòu):
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:tx="http://www.springframework.org/schema/tx"
- xsi:schemalocation
- schemaLocation定義了namespace下面可用的屬性试伙,屬性格式等信息
- namespace的schema可以有不同版本,比如spring-beans-3.1.xsd 掂僵,spring-beans-4.1.xsd
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
2.2namespace
- namespace是上文提到的context,即xmlns:context中的context到千,其他同理
2.3element
- element為<context:component-scan="">中的component-scan
- 可以做如此類比:namespace為MySQL中的DB,元素為table湿镀,element為table中的field
- 那namespace可以使用哪些element呢(只需判斷table中定義了哪些field),這就是上面的schemaLocation的作用了禀梳,如下是schemaLocation value =http://www.springframework.org/schema/context/spring-context-4.1.xsd的大致內(nèi)容
- 可以看到context下可以定義annotation-config,component-scan等元素
- 可以看成其中component-scan中定義了可以使用的field,如base-package肠骆,及其use為required不可或缺
<xsd:schema xmlns="http://www.springframework.org/schema/context" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:tool="http://www.springframework.org/schema/tool" targetNamespace="http://www.springframework.org/schema/context" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xsd:import namespace="http://www.springframework.org/schema/beans" schemaLocation="https://www.springframework.org/schema/beans/spring-beans-4.1.xsd"/>
<xsd:import namespace="http://www.springframework.org/schema/tool" schemaLocation="https://www.springframework.org/schema/tool/spring-tool-4.1.xsd"/>
<xsd:annotation>...</xsd:annotation>
<xsd:complexType name="propertyPlaceholder">...</xsd:complexType>
<xsd:element name="property-placeholder">...</xsd:element>
<xsd:element name="property-override">...</xsd:element>
<xsd:element name="annotation-config">...</xsd:element>
<xsd:element name="component-scan">
<xsd:annotation>...</xsd:annotation>
<xsd:complexType>
<xsd:sequence>...</xsd:sequence>
<xsd:attribute name="base-package" type="xsd:string" use="required">... </xsd:attribute>
<xsd:attribute name="resource-pattern" type="xsd:string">...</xsd:attribute>
<xsd:attribute name="use-default-filters" type="xsd:boolean" default="true">...</xsd:attribute>
<xsd:attribute name="annotation-config" type="xsd:boolean" default="true">...</xsd:attribute>
<xsd:attribute name="name-generator" type="xsd:string">...</xsd:attribute>
<xsd:attribute name="scope-resolver" type="xsd:string">...</xsd:attribute>
<xsd:attribute name="scoped-proxy">...</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:element name="load-time-weaver">...</xsd:element>
<xsd:element name="spring-configured">...</xsd:element>
<xsd:element name="mbean-export">...</xsd:element>
<xsd:element name="mbean-server">...</xsd:element>
<xsd:complexType name="filterType">...</xsd:complexType>
</xsd:schema>
image.png
三.標(biāo)簽的處理
我們知道,注解還是xml的標(biāo)簽塞耕,作用都是起一個(gè)tag的標(biāo)記蚀腿,最終是由其他處理器去發(fā)現(xiàn)這些標(biāo)簽,并根據(jù)標(biāo)簽執(zhí)行不同的邏輯扫外,所以上面這些namespace和element都對應(yīng)著各自的處理器莉钙,且處理器以namespaceHandler:elementHandler層次結(jié)構(gòu)封裝
1.element處理器
- spring jar 包的/META-INF/目錄下,有spring.handlers文件筛谚,該文件定義了若干element 處理器磁玉,如spring-context-4.2.1.RELEASE.jar包下的/META-INF/spring.handlers文件
http\://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler
http\://www.springframework.org/schema/jee=org.springframework.ejb.config.JeeNamespaceHandler
http\://www.springframework.org/schema/lang=org.springframework.scripting.config.LangNamespaceHandler
http\://www.springframework.org/schema/task=org.springframework.scheduling.config.TaskNamespaceHandler
http\://www.springframework.org/schema/cache=org.springframework.cache.config.CacheNamespaceHandler
- 再看ContextNamespaceHandler類
- 針對component-scan可以看到new ComponentScanBeanDefinitionParser()
public class ContextNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());
registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());
registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());
registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());
}
}
- 查看父類NamespaceHandlerSupport實(shí)現(xiàn)子類
- 大概有13個(gè)實(shí)現(xiàn)類
- 且分布在不同的jar包中,比如AopNamespaceHandler子類在spring-aop-4.2.1.RELEASE.jar包中**
- 如此說明我們可以定義自己namespace處理類驾讲,并保存到/META-INF/spring.handlers中
image.png
public class AopNamespaceHandler extends NamespaceHandlerSupport {
/**
* Register the {@link BeanDefinitionParser BeanDefinitionParsers} for the
* '{@code config}', '{@code spring-configured}', '{@code aspectj-autoproxy}'
* and '{@code scoped-proxy}' tags.
*/
@Override
public void init() {
// In 2.0 XSD as well as in 2.1 XSD.
registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
// Only in 2.0 XSD: moved to context namespace as of 2.1
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}
}