spring-schema文件解析(-)

这篇博客是作者关于Spring Schema解析的初步学习记录,适合新手参考。内容包括了解XML基础,学习w3school的schema课程,以及熟悉Java和Spring的使用。博主通过分析spring-beans-4.3.xsd文件,讲解如何自定义schema、NamesepaceHandler,以及创建BeanDefinitionParser和BeanNamespaceHandler。此外,还展示了自定义实体类、配置文件和测试类的示例。虽然尝试编写复杂自定义schema时遇到问题,但博主计划后续补充相关内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

由于作者这方面也是新手,故而大神可以直接略过,权当自己留下的笔记,谬误之处勿喷~
要学习spring schemas及其解析过程,我们应该首先:
1. 熟悉XML/XHTML的基本指示
2. w3school schema课程

3. java及Spring熟练使用

接下来正式开始

首先来看一个spring-beans-4.3.xsd的文件主要内容:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>

<xsd:schema xmlns="http://www.springframework.org/schema/beans"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            targetNamespace="http://www.springframework.org/schema/beans">

    <xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>

    <xsd:annotation>
        <xsd:documentation><![CDATA[
	Spring XML Beans Schema, version 4.3
	Authors: Juergen Hoeller, Rob Harrop, Mark Fisher, Chris Beams

	This defines a simple and consistent way of creating a namespace
	of JavaBeans objects, managed by a Spring BeanFactory, read by
	XmlBeanDefinitionReader (with DefaultBeanDefinitionDocumentReader).

	This document type is used by most Spring functionality, including
	web application contexts, which are based on bean factories.

	Each "bean" element in this document defines a JavaBean.
	Typically the bean class is specified, along with JavaBean properties
	and/or constructor arguments.

	A bean instance can be a "singleton" (shared instance) or a "prototype"
	(independent instance). Further scopes can be provided by extended
	bean factories, for example in a web environment.

	References among beans are supported, that is, setting a JavaBean property
	or a constructor argument to refer to another bean in the same factory
	(or an ancestor factory).

	As alternative to bean references, "inner bean definitions" can be used.
	Such inner beans do not have an independent lifecycle; they are typically
	anonymous nested objects that share the scope of their containing bean.

	There is also support for lists, sets, maps, and java.util.Properties
	as bean property types or constructor argument types.
		]]></xsd:documentation>
    </xsd:annotation>

    <!-- base types -->
    <!--抽象的基础符合类型-->
    <xsd:complexType name="identifiedType" abstract="true">
        <xsd:annotation>
            <xsd:documentation><![CDATA[
	The unique identifier for a bean. The scope of the identifier
	is the enclosing bean factory.
			]]></xsd:documentation>
        </xsd:annotation>
        <xsd:attribute name="id" type="xsd:string">
            <xsd:annotation>
                <xsd:documentation><![CDATA[
	The unique identifier for a bean. A bean id may not be used more than once
	within the same <beans> element.
				]]></xsd:documentation>
            </xsd:annotation>
        </xsd:attribute>
    </xsd:complexType>

    <!-- Top-level <beans> tag -->
    <!-- beans标签 -->
    <!--doc: beans标签bean元素和其他元素的容器,也是xml配置文件的根元素,允许所有嵌套bean的默认值。 -->
    <!--beans标签也可以嵌套于beans标签体内 ---- 出于定义一个有确定默认值的beans子集或者用于注册profles并激活profile的目的-->
    <!--注意:此类beans标签必须被声明为spring beans xml config的最后一个元素-->
    <xsd:element name="beans">
        <xsd:annotation>
            <xsd:documentation><![CDATA[
	Container for <bean> and other elements, typically the root element in the document.
	Allows the definition of default values for all nested bean definitions. May itself
	be nested for the purpose of defining a subset of beans with certain default values or
	to be registered only when certain profile(s) are active. Any such nested <beans> element
	must be declared as the last element in the document.
			]]></xsd:documentation>
        </xsd:annotation>
        <xsd:complexType>
            <xsd:sequence>
                <!--定义了 description, import, alias, bean, beans标签,每个标签都一个出现一次或多次。
                    其中description必须放在第一位,可以出现0此或多次;
                    其他三个标签可以没有先后顺序,也可以是出现0次或多次
                    beans标签必须放在末位;

                -->
                <!--
                    定义了一个可选的属性:profile,类型string
                -->
                <xsd:element ref="description" minOccurs="0"/>
                <xsd:choice minOccurs="0" maxOccurs="unbounded">
                    <xsd:element ref="import"/>
                    <xsd:element ref="alias"/>
                    <xsd:element ref="bean"/>
                    <xsd:any namespace="##other" processContents="strict" minOccurs="0" maxOccurs="unbounded"/>
                </xsd:choice>
                <xsd:element ref="beans" minOccurs="0" maxOccurs="unbounded"/>
            </xsd:sequence>
            <xsd:attribute name="profile" use="optional" type="xsd:string">
                <!--profiles的集合是为了确定将要解析的beans集合,即是此刻哪一个beans标签体内的元素将要被解析,
                多个profile可以用空格, 逗号, 分号分割-->
                <!--如果在激活文件时,一个或多个profile被激活,则对应的beans标签体内的元素被解析, 其中所有的bean都会被注册 -->
                <!--如果解析时,没有对应的profile被激活,那么全部的元素和它的内容都将被忽略。-->
                <!--如果一个profile前缀加上了否定符号"!"
                    <beans profile="p1,!p2">
                    表明p1被激活而p2未被激活
                -->
                <!--profiles可通过以下两种方式被激活:
                程序式配置:
                    ConfigurableEnvironment#setActiveProfiles(String...)
			        ConfigurableEnvironment#setDefaultProfiles(String...)
			    属性配置式(可通过启动时的 -D 系统属性, 环境变量或者servlet context init params):
			        spring.profiles.active=p1,p2
			        spring.profiles.default=p1,p2
                -->
                <xsd:annotation>
                    <xsd:documentation><![CDATA[
	The set of profiles for which this <beans> element should be parsed. Multiple profiles
	can be separated by spaces, commas, or semi-colons.

	If one or more of the specified profiles are active at time of parsing, the <beans>
	element will be parsed, and all of its <bean> elements registered, <import>
	elements followed, etc.  If none of the specified profiles are active at time of
	parsing, then the entire element and its contents will be ignored.

	If a profile is prefixed with the NOT operator '!', e.g.

		<beans profile="p1,!p2">

	indicates that the <beans> element should be parsed if profile "p1" is active or
	if profile "p2" is not active.

	Profiles are activated in one of two ways:
		Programmatic:
			ConfigurableEnvironment#setActiveProfiles(String...)
			ConfigurableEnvironment#setDefaultProfiles(String...)

		Properties (typically through -D system properties, environment variables, or
		servlet context init params):
			spring.profiles.active=p1,p2
			spring.profiles.default=p1,p2
					]]></xsd:documentation>
                </xsd:annotation>
            </xsd:attribute>
            <!--定义默认属性:默认延迟加载:default-lazy-init:-->
            <!--doc: 默认的延迟加载值,请看bean标签的lazy-init属性, 默认值是default,表示从嵌套的外部beans中继承,否则返回false -->
            <xsd:attribute name="default-lazy-init" default="default" type="defaultable-boolean">
                <xsd:annotation>
                    <xsd:documentation><![CDATA[
	The default 'lazy-init' value; see the documentation for the
	'lazy-init' attribute of the 'bean' element. The default is "default",
	indicating inheritance from outer 'beans' sections in case of nesting,
	otherwise falling back to "false".
					]]></xsd:documentation>
                </xsd:annotation>
            </xsd:attribute>
            <!--默认的“合并”值; 请参阅各种集合元素的“合并”属性文档。 缺省值为“default”,表示嵌套时从外部“bean”部分继承,否则返回“false”。-->
            <xsd:attribute name="default-merge" default="default" type="defaultable-boolean">
                <xsd:annotation>
                    <xsd:documentation><![CDATA[
	The default 'merge' value; see the documentation for the 'merge'
	attribute of the various collection elements. The default is "default",
	indicating inheritance from outer 'beans' sections in case of nesting,
	otherwise falling back to "false".
					]]></xsd:documentation>
                </xsd:annotation>
            </xsd:attribute>
            <!--默认的autowire值, 请参阅bean元素的autowire属性文档, 默认值是default, 表明嵌套时从外部beans继承, 否则返回false-->
            <!--无外部驱动的自动装配-->
            <!--定义了autowire的自动装配的可选枚举值: default, no, byname, byType, constructor-->
            <xsd:attribute name="default-autowire" default="default">
                <xsd:annotation>
                    <xsd:documentation><![CDATA[
	The default 'autowire' value; see the documentation for the
	'autowire' attribute of the 'bean' element. The default is "default",
	indicating inheritance from outer 'beans' sections in case of nesting,
	otherwise falling back to "no" (i.e. no externally driven autowiring).
					]]></xsd:documentation>
                </xsd:annotation>
                <xsd:simpleType>
                    <xsd:restriction base="xsd:NMTOKEN">
                        <xsd:enumeration value="default"/>
                        <xsd:enumeration value="no"/>
                        <xsd:enumeration value="byName"/>
                        <xsd:enumeration value="byType"/>
                        <xsd:enumeration value="constructor"/>
                    </xsd:restriction>
                </xsd:simpleType>
            </xsd:attribute>
            <!--这个部分没有太看懂,看个大概 -->
            <!--默认装配候选值:
                用于标识autowire的候选值的默认bean名称匹配模式, 如*Service, *Dao, 或者 “*Service, *Dao”
                详细请参阅bean的autowire-candidate属性的更多细节
            -->
            <xsd:attribute name="default-autowire-candidates" type="xsd:string">
                <xsd:annotation>
                    <xsd:documentation><![CDATA[
	A default bean name pattern for identifying autowire candidates:
	e.g. "*Service", "data*", "*Service*", "data*Service".
	Also accepts a comma-separated list of patterns: e.g. "*Service,*Dao".
	See the documentation for the 'autowire-candidate' attribute of the
	'bean' element for the semantic details of autowire candidate beans.
					]]></xsd:documentation>
                </xsd:annotation>
            </xsd:attribute>
            <!--默认初始化方法: 参看bena的init-method属性-->
            <xsd:attribute name="default-init-method" type="xsd:string">
                <xsd:annotation>
                    <xsd:documentation><![CDATA[
	The default 'init-method' value; see the documentation for the
	'init-method' attribute of the 'bean' element.
					]]></xsd:documentation>
                </xsd:annotation>
            </xsd:attribute>
            <!--默认销毁方法: 请看bean元素的destroy-method属性-->
            <xsd:attribute name="default-destroy-method" type="xsd:string">
                <xsd:annotation>
                    <xsd:documentation><![CDATA[
	The default 'destroy-method' value; see the documentation for the
	'destroy-method' attribute of the 'bean' element.
					]]></xsd:documentation>
                </xsd:annotation>
            </xsd:attribute>
            <xsd:anyAttribute namespace="##other" processContents="lax"/>
        </xsd:complexType>
    </xsd:element>

    <!--beans元素默认引用的第一个元素,必须出现在beans元素的首个元素,可出现0次或多次 -->
    <!--包含描述封闭元素用途的信息文本。主要用于XML bean定义文档的用户参考手册。-->
    <xsd:element name="description">
        <xsd:annotation>
            <xsd:documentation><![CDATA[
	Contains informative text describing the purpose of the enclosing element.
	Used primarily for user documentation of XML bean definition documents.
			]]></xsd:documentation>
        </xsd:annotation>
        <xsd:complexType mixed="true">
            <xsd:choice minOccurs="0" maxOccurs="unbounded"/>
        </xsd:complexType>
    </xsd:element>

    <!--import元素:声明要导入的xml bean定义源文件-->
    <!--属性:
        resource:必须指定。用于指定xml源文件的相对路径
    -->
    <xsd:element name="import">
        <xsd:annotation>
            <xsd:documentation source="java:org.springframework.core.io.Resource"><![CDATA[
	Specifies an XML bean definition resource to import.
			]]></xsd:documentation>
        </xsd:annotation>
        <xsd:complexType>
            <xsd:complexContent>
                <xsd:restriction base="xsd:anyType">
                    <xsd:attribute name="resource" type="xsd:string" use="required">
                        <xsd:annotation>
                            <xsd:documentation><![CDATA[
	The relative resource location of the XML (bean definition) file to import,
	for example "myImport.xml" or "includes/myImport.xml" or "../myImport.xml".
							]]></xsd:documentation>
                        </xsd:annotation>
                    </xsd:attribute>
                </xsd:restriction>
            </xsd:complexContent>
        </xsd:complexType>
    </xsd:element>

    <!--alias元素:为一个bean定义别名(该bean可以声明在不同的源文件中)-->
    <!--属性:
        name: 需要被定义别名的bean, 必须
        alias: bean的别名,必须
    -->
    <xsd:element name="alias">
        <xsd:annotation>
            <xsd:documentation><![CDATA[
	Defines an alias for a bean (which can reside in a different definition
	resource).
			]]></xsd:documentation>
        </xsd:annotation>
        <xsd:complexType>
            <xsd:complexContent>
                <xsd:restriction base="xsd:anyType">
                    <xsd:attribute name="name" type="xsd:string" use="required">
                        <xsd:annotation>
                            <xsd:documentation><![CDATA[
	The name of the bean to define an alias for.
							]]></xsd:documentation>
                        </xsd:annotation>
                    </xsd:attribute>
                    <xsd:attribute name="alias" type="xsd:string" use="required">
                        <xsd:annotation>
                            <xsd:documentation><![CDATA[
	The alias name to define for the bean.
							]]></xsd:documentation>
                        </xsd:annotation>
                    </xsd:attribute>
                </xsd:restriction>
            </xsd:complexContent>
        </xsd:complexType>
    </xsd:element>

    <!--bean元素公用组元素-->
    <xsd:group name="beanElements">
        <xsd:sequence>
            <xsd:element ref="description" minOccurs="0"/>
            <xsd:choice minOccurs="0" maxOccurs="unbounded">
                <xsd:element ref="meta"/>
                <xsd:element ref="constructor-arg"/>
                <xsd:element ref="property"/>
                <xsd:element ref="qualifier"/>
                <xsd:element ref="lookup-method"/>
                <xsd:element ref="replaced-method"/>
                <xsd:any namespace="##other" processContents="strict" minOccurs="0" maxOccurs="unbounded"/>
            </xsd:choice>
        </xsd:sequence>
    </xsd:group>
    <!--bean属性组元素
        name:可以用来创建一个或多个非法ID用来标识一个bean, 多个别名可以用一个或多个逗号, 空格,分号或他们的组合来分隔
        class: bean的全类名,除非它是作为一个父bean为子bean服务
        parent:父bean定义。如果未声明全类名,则会使用父类的class,但是也可以重写。
                在重写的额情况下,子类必须与父类兼容,如接受父类的属性和构造器参数(如果有的话)
                子bean定义将会继承构造器参数,属性值和重写的父类方法并且可选添加新值。
                如果声明初始化方法,销毁方法和工厂bean,工厂方法,则将重写父类的相关设置。
        scope:bean的scope。默认singleton。任何通过给定id调用该bean的方法都会获得一个该bean的共享单实例。
                或者prototype:每次调用都会产生新的实例。
                默认情况下是singleton。除非它继承了父类的scope
                singleton是最常用的,并且是多线程情况下的最理想选择。其他选项如request和session,通常由扩展bena工厂支持。
                如web环境下
                内部bean将继承包含他们的bean的scope。如果包含他们的bean是一个singleton,则内部bean是singleton;
                如果包含他们的bean是一个prototype,则内部bean也是一个prototype
        abstract:抽象bean,用来告诉容器不要实例化该bean,而指示作为一个父bean用来创建子类bean。
                  默认情况下是false,指定true用来告诉容器任何情况下都不要尝试来实例化该bean
                  该属性不会被继承,每一个bean都需要单独指定该属性
        lazy-init:表明该bean释放应该被延迟初始化,如果false,它将会被容器工厂启动时进行单实例初始化。 默认值false
                  注意:该属性将不会被子bean继承。因此,每创建一个bean定义都需要单独指定该属性。它可能从beans属性中default-lazy-init属性
                  继承和共享。或者可能从嵌套的外部bean继承(如不同的profile)
        autowire:控制bean的属性是否自动装配:
                  这是一个不要再配置文件的bean定义中显式编码的无意识的自动过程。spring容器会自动解决依赖。有效默认值为no。
                    共有4种模式:
                    no:传统的spring默认模式。无自动装配。bean引用必须在xml文件使用ref元素或ref属性显示声明。
                        我们仍建议这样引用因为这会使文档更加明确。
                        注意:这个默认模式允许注解驱动的自动装配。如果被激活,no仅指外部驱动的自动装配,而不会影响bean本身的自动装配需求
                    byname:通过属性名称自动装配。如果一个Cat类暴露出dog属性。spring将会尝试把当前容器中名称为dog的bean装配上去。
                            如果没有匹配的名称,则什么也不会发生。
                    bytype:如果容器中有一个bean的类型与该属性的类型相同,则会自动装配。如果有超过一个,则会引发致命错误。
                            你将不能通过bytype进行自动装配。如果没有,也不会发生异常。
                    constructor:通过构造函数类似于bytype装配,如果bean工厂没有符合构造参数类型的bean,则会发生致命异常
                    注意:这个属性不会继承,每个bean都需要单独指定。可能通过外部的beans中的default-autowire继承。或者通过
                          外部嵌套的bean继承。
        depends-on: 该bean初始化所依赖的beans。bean工厂将会确保在该bean初始化之前去初始化这些beans
                    注意:这些依赖关系通常通过bean属性或者构造参数进行表示。这个属性应该其他类型依赖的必须,如静态或数据库启动准备(没太看懂)
                    注意:该属性不能被继承,每一个元素都应该单独指定
        autowire-candidate:当装配其他bean时,容器寻找匹配的bean时,该bean是否被认为是匹配的候选人。
                            注意:这不会影响name的显示引用。因为即使未被指定未继承人,该bean依然会被解析。
        primary:指定该bean应该被优先装配当有多个候选人满足装配一个单值依赖。如果在候选人中存在一个primary bean,它将会被优先装配。
        inti-method:在设置属性后要执行的自定义初始化方法的名称。该方法不能有参数,但是可以抛异常。
                         这是一个实现initializingBean接口或者@Postconstructor注解的替代方法
        destroy-method:在bean容器关闭时的自定义销毁方法。该方法不能有参数,但是可以抛异常。
                        这是实现DisposableBean接口的以及java Closeable/Autocloseable接口以及@Predestroy注解的替代方法
                        注意:只有该bean的生命周期被容器全权控制的bean才可以执行该方法--通常情况下是单实例bean,其他scopebean不适用。
        factory-method: 创建此对象的工厂方法的名称。如果需要参数,需要通过constructor-arg参数来指定工厂的参数。自动装配不适用于工厂方法
                        如果同时存在class属性,工厂方法将是静态的,通常这将会与被构造对象的类相同--例如,工厂方法被用作替代构造函数。
                        但是,它可能是不同的类。在这个情况下,创建的对象将不是class属性指定的类,这与工厂bean行为类似。
                        如果存在factory-bean属性且class属性没有被使用, 通过给定的bean名称调用getBean()获得返回的object方法将会是一个实例方法。
                        该factorybean可以被定义为singleton或者prototype
                        工厂方法可以有任意数量的参数u,不支持自动装配。结合构造函数索引使用工厂方法进行构造注入。
                        setter注入可以结合工厂方法使用。方法注入不能,因为工厂方法返回一个容器创建的将会被使用的bean实例。

        factory-bean: 使用工厂方法时class属性的替代品。
                           如果声明该属性,则不能使用class属性。
                           该属性必须被设置为当前工厂或父工厂中包含的相关工厂方法的bean名称。这允许工厂进行自动依赖配置,
                           并使用实例方法(而不是静态方法)
    -->
    <xsd:attributeGroup name="beanAttributes">
        <xsd:attribute name="name" type="xsd:string">
            <xsd:annotation>
                <xsd:documentation><![CDATA[
	Can be used to create one or more aliases illegal in an (XML) id.
	Multiple aliases can be separated by any number of spaces, commas,
	or semi-colons (or indeed any mixture of the three).
				]]></xsd:documentation>
            </xsd:annotation>
        </xsd:attribute>
        <xsd:attribute name="class" type="xsd:string">
            <xsd:annotation>
                <xsd:documentation source="java:java.lang.Class"><![CDATA[
	The fully qualified name of the bean's class, except if it serves only
	as a parent definition for child bean definitions.
				]]></xsd:documentation>
            </xsd:annotation>
        </xsd:attribute>
        <xsd:attribute name="parent" type="xsd:string">
            <xsd:annotation>
                <xsd:documentation><![CDATA[
	The name of the parent bean definition.

	Will use the bean class of the parent if none is specified, but can
	also override it. In the latter case, the child bean class must be
	compatible with the parent, i.e. accept the parent's property values
	and constructor argument values, if any.

	A child bean definition will inherit constructor argument values,
	property values and method overrides from the parent, with the option
	to add new values. If init method, destroy method, factory bean and/or
	factory method are specified, they will override the corresponding
	parent settings.

	The remaining settings will always be taken from the child definition:
	depends on, autowire mode, scope, lazy init.
				]]></xsd:documentation>
            </xsd:annotation>
        </xsd:attribute>
        <xsd:attribute name="scope" type="xsd:string">
            <xsd:annotation>
                <xsd:documentation><![CDATA[
	The scope of this bean: typically "singleton" (one shared instance,
	which will be returned by all calls to getBean with the given id), or
	"prototype" (independent instance resulting from each call to getBean).

	By default, a bean will be a singleton, unless the bean has a parent
	bean definition in which case it will inherit the parent's scope.

	Singletons are most commonly used, and are ideal for multi-threaded
	service objects. Further scopes, such as "request" or "session", might
	be supported by extended bean factories (e.g. in a web environment).

	Inner bean definitions inherit the scope of their containing bean
	definition, unless explicitly specified: The inner bean will be a
	singleton if the containing bean is a singleton, and a prototype if
	the containing bean is a prototype, etc.
				]]></xsd:documentation>
            </xsd:annotation>
        </xsd:attribute>
        <xsd:attribute name="abstract" type="xsd:boolean">
            <xsd:annotation>
                <xsd:documentation><![CDATA[
	Is this bean "abstract", that is, not meant to be instantiated itself
	but rather just serving as parent for concrete child bean definitions?
	The default is "false". Specify "true" to tell the bean factory to not
	try to instantiate that particular bean in any case.

	Note: This attribute will not be inherited by child bean definitions.
	Hence, it needs to be specified per abstract bean definition.
				]]></xsd:documentation>
            </xsd:annotation>
        </xsd:attribute>
        <!--
        -->
        <xsd:attribute name="lazy-init" default="default" type="defaultable-boolean">
            <xsd:annotation>
                <xsd:documentation><![CDATA[
	Indicates whether this bean is to be lazily initialized. If "false",
	it will be instantiated on startup by bean factories that perform eager
	initialization of singletons. The effective default is "false".

	Note: This attribute will not be inherited by child bean definitions.
	Hence, it needs to be specified per concrete bean definition. It can be
	shared through the 'default-lazy-init' attribute at the 'beans' level
	and potentially inherited from outer 'beans' defaults in case of nested
	'beans' sections (e.g. with different profiles).
				]]></xsd:documentation>
            </xsd:annotation>
        </xsd:attribute>
        <xsd:attribute name="autowire" default="default">
            <xsd:annotation>
                <xsd:documentation><![CDATA[
	Controls whether bean properties are "autowired".
	This is an automagical process in which bean references don't need
	to be coded explicitly in the XML bean definition file, but rather the
	Spring container works out dependencies. The effective default is "no".

	There are 4 modes:

	1. "no"
	The traditional Spring default. No automagical wiring. Bean references
	must be defined in the XML file via the <ref/> element (or "ref"
	attribute). We recommend this in most cases as it makes documentation
	more explicit.

	Note that this default mode also allows for annotation-driven autowiring,
	if activated. "no" refers to externally driven autowiring only, not
	affecting any autowiring demands that the bean class itself expresses.

	2. "byName"
	Autowiring by property name. If a bean of class Cat exposes a "dog"
	property, Spring will try to set this to the value of the bean "dog"
	in the current container. If there is no matching bean by name, nothing
	special happens.

	3. "byType"
	Autowiring if there is exactly one bean of the property type in the
	container. If there is more than one, a fatal error is raised, and
	you cannot use byType autowiring for that bean. If there is none,
	nothing special happens.

	4. "constructor"
	Analogous to "byType" for constructor arguments. If there is not exactly
	one bean of the constructor argument type in the bean factory, a fatal
	error is raised.

	Note that explicit dependencies, i.e. "property" and "constructor-arg"
	elements, always override autowiring.

	Note: This attribute will not be inherited by child bean definitions.
	Hence, it needs to be specified per concrete bean definition. It can be
	shared through the 'default-autowire' attribute at the 'beans' level
	and potentially inherited from outer 'beans' defaults in case of nested
	'beans' sections (e.g. with different profiles).
				]]></xsd:documentation>
            </xsd:annotation>
            <xsd:simpleType>
                <xsd:restriction base="xsd:NMTOKEN">
                    <xsd:enumeration value="default"/>
                    <xsd:enumeration value="no"/>
                    <xsd:enumeration value="byName"/>
                    <xsd:enumeration value="byType"/>
                    <xsd:enumeration value="constructor"/>
                </xsd:restriction>
            </xsd:simpleType>
        </xsd:attribute>
        <!--
        -->
        <xsd:attribute name="depends-on" type="xsd:string">
            <xsd:annotation>
                <xsd:documentation><![CDATA[
	The names of the beans that this bean depends on being initialized.
	The bean factory will guarantee that these beans get initialized
	before this bean.

	Note that dependencies are normally expressed through bean properties
	or constructor arguments. This property should just be necessary for
	other kinds of dependencies like statics (*ugh*) or database preparation
	on startup.

	Note: This attribute will not be inherited by child bean definitions.
	Hence, it needs to be specified per concrete bean definition.
				]]></xsd:documentation>
            </xsd:annotation>
        </xsd:attribute>
        <xsd:attribute name="autowire-candidate" default="default" type="defaultable-boolean">
            <xsd:annotation>
                <xsd:documentation><![CDATA[
	Indicates whether or not this bean should be considered when looking
	for matching candidates to satisfy another bean's autowiring requirements.
	Note that this does not affect explicit references by name, which will get
	resolved even if the specified bean is not marked as an autowire candidate.
				]]></xsd:documentation>
            </xsd:annotation>
        </xsd:attribute>
        <xsd:attribute name="primary" type="xsd:boolean">
            <xsd:annotation>
                <xsd:documentation><![CDATA[
	Specifies that this bean should be given preference when multiple
	candidates are qualified to autowire a single-valued dependency.
	If exactly one 'primary' bean exists among the candidates, it
	will be the autowired value.
				]]></xsd:documentation>
            </xsd:annotation>
        </xsd:attribute>
        <xsd:attribute name="init-method" type="xsd:string">
            <xsd:annotation>
                <xsd:documentation><![CDATA[
	The name of the custom initialization method to invoke after setting
	bean properties. The method must have no arguments, but may throw any
	exception.

	This is an alternative to implementing Spring's InitializingBean
	interface or marking a method with the PostConstruct annotation.
				]]></xsd:documentation>
            </xsd:annotation>
        </xsd:attribute>
        <xsd:attribute name="destroy-method" type="xsd:string">
            <xsd:annotation>
                <xsd:documentation><![CDATA[
	The name of the custom destroy method to invoke on bean factory shutdown.
	The method must have no arguments, but may throw any exception.

	This is an alternative to implementing Spring's DisposableBean
	interface or the standard Java Closeable/AutoCloseable interface,
	or marking a method with the PreDestroy annotation.

	Note: Only invoked on beans whose lifecycle is under the full
	control of the factory - which is always the case for singletons,
	but not guaranteed for any other scope.
				]]></xsd:documentation>
            </xsd:annotation>
        </xsd:attribute>
        <xsd:attribute name="factory-method" type="xsd:string">
            <xsd:annotation>
                <xsd:documentation><![CDATA[
	The name of a factory method to use to create this object. Use
	constructor-arg elements to specify arguments to the factory method,
	if it takes arguments. Autowiring does not apply to factory methods.

	If the "class" attribute is present, the factory method will be a static
	method on the class specified by the "class" attribute on this bean
	definition. Often this will be the same class as that of the constructed
	object - for example, when the factory method is used as an alternative
	to a constructor. However, it may be on a different class. In that case,
	the created object will *not* be of the class specified in the "class"
	attribute. This is analogous to FactoryBean behavior.

	If the "factory-bean" attribute is present, the "class" attribute is not
	used, and the factory method will be an instance method on the object
	returned from a getBean call with the specified bean name. The factory
	bean may be defined as a singleton or a prototype.

	The factory method can have any number of arguments. Autowiring is not
	supported. Use indexed constructor-arg elements in conjunction with the
	factory-method attribute.

	Setter Injection can be used in conjunction with a factory method.
	Method Injection cannot, as the factory method returns an instance,
	which will be used when the container creates the bean.
				]]></xsd:documentation>
            </xsd:annotation>
        </xsd:attribute>
        <xsd:attribute name="factory-bean" type="xsd:string">
            <xsd:annotation>
                <xsd:documentation><![CDATA[
	Alternative to class attribute for factory-method usage.
	If this is specified, no class attribute should be used.
	This must be set to the name of a bean in the current or
	ancestor factories that contains the relevant factory method.
	This allows the factory itself to be configured using Dependency
	Injection, and an instance (rather than static) method to be used.
				]]></xsd:documentation>
            </xsd:annotation>
        </xsd:attribute>
        <xsd:anyAttribute namespace="##other" processContents="lax"/>
    </xsd:attributeGroup>

    <xsd:element name="meta" type="metaType">
        <xsd:annotation>
            <xsd:documentation><![CDATA[
	Arbitrary metadata attached to a bean definition.
			]]></xsd:documentation>
        </xsd:annotation>
    </xsd:element>

    <!--metaType:
        元数据类型:bean中可定义元数据的key,value对,两个属性必须
    -->
    <xsd:complexType name="metaType">
        <xsd:attribute name="key" type="xsd:string" use="required">
            <xsd:annotation>
                <xsd:documentation><![CDATA[
	The key name of the metadata attribute being defined.
				]]></xsd:documentation>
            </xsd:annotation>
        </xsd:attribute>
        <xsd:attribute name="value" type="xsd:string" use="required">
            <xsd:annotation>
                <xsd:documentation><![CDATA[
	The value of the metadata attribute being defined (as a simple String).
				]]></xsd:documentation>
            </xsd:annotation>
        </xsd:attribute>
    </xsd:complexType>

    <!--bean定义:
        使用上面定义的两个复合类型:
            beanElements
            beanAttributes
    -->
    <xsd:element name="bean">
        <xsd:annotation>
            <xsd:documentation source="java:org.springframework.beans.factory.config.BeanDefinition"><![CDATA[
	Defines a single (usually named) bean.

	A bean definition may contain nested tags for constructor arguments,
	property values, lookup methods, and replaced methods. Mixing constructor
	injection and setter injection on the same bean is explicitly supported.
			]]></xsd:documentation>
        </xsd:annotation>
        <xsd:complexType>
            <xsd:complexContent>
                <xsd:extension base="identifiedType">
                    <xsd:group ref="beanElements"/>
                    <xsd:attributeGroup ref="beanAttributes"/>
                </xsd:extension>
            </xsd:complexContent>
        </xsd:complexType>
    </xsd:element>

    <!--constructor-arg:
        bean definitions可以声明0个或多个构造参数,这将会替代默认的自动装配constructor。
        构造函数参数通过构造参数列表索引或者通过参数类型进行关联;
        注意:一个泛型参数值智慧被使用一次,而不是可能匹配多次
        构造函数元素也可以在静态或实例工厂方法进行结合注入时使用
        定义了多个元素类型引用:如bean ref idref value null array list set map props等,
        可以声明一次或多次
    -->
    <xsd:element name="constructor-arg">
        <xsd:annotation>
            <xsd:documentation source="java:org.springframework.beans.factory.config.ConstructorArgumentValues">
                <![CDATA[
	Bean definitions can specify zero or more constructor arguments.
	This is an alternative to "autowire constructor".
	Arguments correspond to either a specific index of the constructor
	argument list or are supposed to be matched generically by type.

	Note: A single generic argument value will just be used once, rather
	than potentially matched multiple times (as of Spring 1.1).

	constructor-arg elements are also used in with the
	factory-method element to construct beans using static or instance
	factory methods.
			]]></xsd:documentation>
        </xsd:annotation>
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element ref="description" minOccurs="0"/>
                <xsd:choice minOccurs="0" maxOccurs="1">
                    <xsd:element ref="bean"/>
                    <xsd:element ref="ref"/>
                    <xsd:element ref="idref"/>
                    <xsd:element ref="value"/>
                    <xsd:element ref="null"/>
                    <xsd:element ref="array"/>
                    <xsd:element ref="list"/>
                    <xsd:element ref="set"/>
                    <xsd:element ref="map"/>
                    <xsd:element ref="props"/>
                    <xsd:any namespace="##other" processContents="strict"/>
                </xsd:choice>
            </xsd:sequence>
            <!--index:构造函数参数里的确切索引位置。是为了避免两个函数参数类型相同的而出现混淆的情况-->
            <xsd:attribute name="index" type="xsd:string">
                <xsd:annotation>
                    <xsd:documentation><![CDATA[
	The exact index of the argument in the constructor argument list.
	Only needed to avoid ambiguities, e.g. in case of 2 arguments of
	the exact same type.
					]]></xsd:documentation>
                </xsd:annotation>
            </xsd:attribute>
            <!--type:确切的构造函数参数类型。只是为了避免混淆。例如,两个单参数构造函数都可能从String转换而来-->
            <xsd:attribute name="type" type="xsd:string">
                <xsd:annotation>
                    <xsd:documentation><![CDATA[
	The exact type of the constructor argument. Only needed to avoid
	ambiguities, e.g. in case of 2 single argument constructors
	that can both be converted from a String.
					]]></xsd:documentation>
                </xsd:annotation>
            </xsd:attribute>
            <!--name: 构造函数参数表中参数的确定名称,仅为了避免混淆。-->
            <xsd:attribute name="name" type="xsd:string">
                <xsd:annotation>
                    <xsd:documentation><![CDATA[
	The exact name of the argument in the constructor argument list.
	Only needed to avoid ambiguities, e.g. in case of 2 arguments of
	the exact same type. Note: This requires debug symbols to be
	stored in the class file in order to introspect argument names!
					]]></xsd:documentation>
                </xsd:annotation>
            </xsd:attribute>
            <!--ref: <ref bean='...'/>的缩写-->
            <xsd:attribute name="ref" type="xsd:string">
                <xsd:annotation>
                    <xsd:documentation><![CDATA[
	A short-cut alternative to a nested "<ref bean='...'/>" element.
					]]></xsd:documentation>
                </xsd:annotation>
            </xsd:attribute>
            <!--value:<value>...<value/>的缩写-->
            <xsd:attribute name="value" type="xsd:string">
                <xsd:annotation>
                    <xsd:documentation><![CDATA[
	A short-cut alternative to a nested "<value>...<value/>" element.
					]]></xsd:documentation>
                </xsd:annotation>
            </xsd:attribute>
        </xsd:complexType>
    </xsd:element>

    <!--property:
        一个bean definitions可以有0个或多个属性。Properties元素与bean暴露出来的setter方法关联。
        spring指示基元,引用同一个或相关工厂,lists,map和properties中的bean
    -->
    <xsd:element name="property" type="propertyType">
        <xsd:annotation>
            <xsd:documentation><![CDATA[
	Bean definitions can have zero or more properties.
	Property elements correspond to JavaBean setter methods exposed
	by the bean classes. Spring supports primitives, references to other
	beans in the same or related factories, lists, maps and properties.
			]]></xsd:documentation>
        </xsd:annotation>
    </xsd:element>

    <!--qualifier:
            Bean定义可以提供限定符以匹配字段或参数上的注释以实现细粒度的自动导向候选解析。
            type: 默认为Qualifier
            value:非必要
    -->
    <xsd:element name="qualifier">
        <xsd:annotation>
            <xsd:documentation><![CDATA[
	Bean definitions can provide qualifiers to match against annotations
	on a field or parameter for fine-grained autowire candidate resolution.
			]]></xsd:documentation>
        </xsd:annotation>
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element ref="attribute" minOccurs="0" maxOccurs="unbounded"/>
            </xsd:sequence>
            <xsd:attribute name="type" type="xsd:string" default="org.springframework.beans.factory.annotation.Qualifier"/>
            <xsd:attribute name="value" type="xsd:string"/>
        </xsd:complexType>
    </xsd:element>

    <!--
        限定符元素可能包含属性子元素作为键值对。 这些将可用于匹配autowired字段或参数(如果存在)上限定符注释的属性。
    -->
    <xsd:element name="attribute" type="metaType">
        <xsd:annotation>
            <xsd:documentation><![CDATA[
	A qualifier element may contain attribute child elements as key-value
	pairs. These will be available for matching against attributes of a
	qualifier annotation on an autowired field or parameter if present.
			]]></xsd:documentation>
        </xsd:annotation>
    </xsd:element>

    <!--lookup-method:
            lookup-method会使IOC容器重写给定的方法并返回bean属性中指定name的bean。这是方法注入的一种方式、
            它是替代实现BeanFactoryAware接口,在运行时调用getBean()返回非单实例bean的一种非常有效的方式
            因此,方法注入是一种实现代码较小侵入性的选择。
      name:该方法可能有参数传递给目标构造函数或工厂方法。 请注意,出于向后兼容的原因,在给定名称的非抽象方法
            重载的情况下,只有方法的无参数变体才会变成容器驱动的查找方法。考虑使用@Lookup注释以获得更具体的界限。
      bean: lookup-method将会解析成的当前容器或父容器中的bean。通常情况下该bean是prototype,此时每次lookup-method
            调用都返回一个该bean的一个实例。如果未指定,lookup-method方法的返回值将会以类型为基准。
    -->
    <xsd:element name="lookup-method">
        <xsd:annotation>
            <xsd:documentation><![CDATA[
	A lookup method causes the IoC container to override the given method
	and return the bean with the name given in the bean attribute. This is
	a form of Method Injection. It is particularly useful as an alternative
	to implementing the BeanFactoryAware interface, in order to be able to
	make getBean() calls for non-singleton instances at runtime. In this
	case, Method Injection is a less invasive alternative.
			]]></xsd:documentation>
        </xsd:annotation>
        <xsd:complexType>
            <xsd:complexContent>
                <xsd:restriction base="xsd:anyType">
                    <xsd:attribute name="name" type="xsd:string">
                        <xsd:annotation>
                            <xsd:documentation><![CDATA[
	The name of the lookup method. This method may have arguments which
	will be passed on to the target constructor or factory method. Note
	that for backwards compatibility reasons, in a scenario with overloaded
	non-abstract methods of the given name, only the no-arg variant of a
	method will be turned into a container-driven lookup method.
	Consider using the @Lookup annotation for more specific demarcation.
							]]></xsd:documentation>
                        </xsd:annotation>
                    </xsd:attribute>
                    <xsd:attribute name="bean" type="xsd:string">
                        <xsd:annotation>
                            <xsd:documentation><![CDATA[
	The name of the bean in the current or ancestor factories that
	the lookup method should resolve to. Usually this bean will be a
	prototype, in which case the lookup method will return a distinct
	instance on every invocation. If not specified, the lookup method's
	return type will be used for a type-based lookup.
							]]></xsd:documentation>
                        </xsd:annotation>
                    </xsd:attribute>
                </xsd:restriction>
            </xsd:complexContent>
        </xsd:complexType>
    </xsd:element>

    <!--replaced-method:
            类似于lookup-method机制。replaced-nethod元素被 用来控制IOC容器重写:方法注入。该机制允许任意代码覆盖方法。
        属性:
            name:将会被IOC容器替代的方法实现的名称。如果该方法没有被重载,就没有使用arg-type 子元素。
                  如果被重载了,所有被重写的方法都必须使用arg-type子元素。
            replacer: 当前或祖先工厂中MethodReplacer接口实现的Bean名称。 这可能是一个singleton或prototype bean。
                      如果是原型,则每个方法替换都会使用一个新实例。 通常使用单实例。
    -->
    <xsd:element name="replaced-method">
        <xsd:annotation>
            <xsd:documentation><![CDATA[
	Similar to the lookup method mechanism, the replaced-method element
	is used to control IoC container method overriding: Method Injection.
	This mechanism allows the overriding of a method with arbitrary code.
			]]></xsd:documentation>
        </xsd:annotation>
        <xsd:complexType>
            <xsd:sequence>
                <xsd:choice minOccurs="0" maxOccurs="unbounded">
                    <xsd:element ref="arg-type"/>
                </xsd:choice>
            </xsd:sequence>
            <xsd:attribute name="name" type="xsd:string">
                <xsd:annotation>
                    <xsd:documentation><![CDATA[
	The name of the method whose implementation must be replaced by the
	IoC container. If this method is not overloaded, there is no need
	to use arg-type subelements. If this method is overloaded, arg-type
	subelements must be used for all override definitions for the method.
					]]></xsd:documentation>
                </xsd:annotation>
            </xsd:attribute>
            <xsd:attribute name="replacer" type="xsd:string">
                <xsd:annotation>
                    <xsd:documentation source="java:org.springframework.beans.factory.support.MethodReplacer"><![CDATA[
	Bean name of an implementation of the MethodReplacer interface in the
	current or ancestor factories. This may be a singleton or prototype
	bean. If it is a prototype, a new instance will be used for each
	method replacement. Singleton usage is the norm.
					]]></xsd:documentation>
                </xsd:annotation>
            </xsd:attribute>
        </xsd:complexType>
    </xsd:element>


    <!--replaced-method中指定重载方法的参数类型
        match: 指定重载方法的参数,如String,为了方便,通常指定全类名的子字符串,
        因为参数数量将会被建成,所以这种简写通常可以用来保存类型。
    -->
    <xsd:element name="arg-type">
        <xsd:annotation>
            <xsd:documentation><![CDATA[
	Identifies an argument for a replaced method in the event of
	method overloading.
			]]></xsd:documentation>
        </xsd:annotation>
        <xsd:complexType mixed="true">
            <xsd:choice minOccurs="0" maxOccurs="unbounded"/>
            <xsd:attribute name="match" type="xsd:string">
                <xsd:annotation>
                    <xsd:documentation><![CDATA[
	Specification of the type of an overloaded method argument as a String.
	For convenience, this may be a substring of the FQN. E.g. all the
	following would match "java.lang.String":
	- java.lang.String
	- String
	- Str

	As the number of arguments will be checked also, this convenience
	can often be used to save typing.
					]]></xsd:documentation>
                </xsd:annotation>
            </xsd:attribute>
        </xsd:complexType>
    </xsd:element>

    <!--ref:
            定义一个该工厂或外部工厂(父工厂或内部工厂)中的bean引用
            name:被引用bean的名称
            praent:被引用bean所在的父容器
    -->
    <xsd:element name="ref">
        <xsd:annotation>
            <xsd:documentation><![CDATA[
	Defines a reference to another bean in this factory or an external
	factory (parent or included factory).
			]]></xsd:documentation>
        </xsd:annotation>
        <xsd:complexType>
            <xsd:complexContent>
                <xsd:restriction base="xsd:anyType">
                    <xsd:attribute name="bean" type="xsd:string">
                        <xsd:annotation>
                            <xsd:documentation><![CDATA[
	The name of the referenced bean.
							]]></xsd:documentation>
                        </xsd:annotation>
                    </xsd:attribute>
                    <xsd:attribute name="parent" type="xsd:string">
                        <xsd:annotation>
                            <xsd:documentation><![CDATA[
	The name of the referenced bean in a parent factory.
						]]></xsd:documentation>
                        </xsd:annotation>
                    </xsd:attribute>
                </xsd:restriction>
            </xsd:complexContent>
        </xsd:complexType>
    </xsd:element>

    <!--idref:被引用bean的id,该bean可以是本工厂或是外部工厂(父工厂或包含的工厂)
        虽然常规的value元素可以起到相同的效果,但是idref会指示spring容器去检查value月bean的id是否关联。
    -->
    <xsd:element name="idref">
        <xsd:annotation>
            <xsd:documentation><![CDATA[
	The id of another bean in this factory or an external factory
	(parent or included factory).
	While a regular 'value' element could instead be used for the
	same effect, using idref indicates that the Spring container
	should check that the value actually corresponds to a bean id.
			]]></xsd:documentation>
        </xsd:annotation>
        <xsd:complexType>
            <xsd:complexContent>
                <xsd:restriction base="xsd:anyType">
                    <xsd:attribute name="bean" type="xsd:string">
                        <xsd:annotation>
                            <xsd:documentation><![CDATA[
	The name of the referenced bean.
							]]></xsd:documentation>
                        </xsd:annotation>
                    </xsd:attribute>
                </xsd:restriction>
            </xsd:complexContent>
        </xsd:complexType>
    </xsd:element>

    <!--value: 一个代表属性值的String字符串。
               这个属性可以是string,也可以被转换成为需要的类型通过使用JAVABEANS PROPRETYEDITOR 机制。
               这使应用程序开发人员可以编写自定义的ProperyEditor实现从而可以将string转换成任何目标对象。
        注意:这仅适用于简单对象。 通过引用其他bean来填充JavaBean属性来配置更复杂的对象。
            type: 该value将会被转换成的具体的类型。仅在目标属性的类型或者构造函数太过通用的情况下才需要,如集合元素。
    -->
    <xsd:element name="value">
        <xsd:annotation>
            <xsd:documentation><![CDATA[
	Contains a string representation of a property value.
	The property may be a string, or may be converted to the required
	type using the JavaBeans PropertyEditor machinery. This makes it
	possible for application developers to write custom PropertyEditor
	implementations that can convert strings to arbitrary target objects.

	Note that this is recommended for simple objects only. Configure
	more complex objects by populating JavaBean properties with
	references to other beans.
			]]></xsd:documentation>
        </xsd:annotation>
        <xsd:complexType mixed="true">
            <xsd:choice minOccurs="0" maxOccurs="unbounded"/>
            <xsd:attribute name="type" type="xsd:string">
                <xsd:annotation>
                    <xsd:documentation><![CDATA[
	The exact type that the value should be converted to. Only needed
	if the type of the target property or constructor argument is
	too generic: for example, in case of a collection element.
					]]></xsd:documentation>
                </xsd:annotation>
            </xsd:attribute>
        </xsd:complexType>
    </xsd:element>

    <!--null:
            表示Java空值。 必要的,因为一个空的“value”标签将解析为一个空的字符串,除非特殊的PropertyEditor这样做,否则不会解析为空值。
    -->
    <xsd:element name="null">
        <xsd:annotation>
            <xsd:documentation><![CDATA[
	Denotes a Java null value. Necessary because an empty "value" tag
	will resolve to an empty String, which will not be resolved to a
	null value unless a special PropertyEditor does so.
			]]></xsd:documentation>
        </xsd:annotation>
        <xsd:complexType mixed="true">
            <xsd:choice minOccurs="0" maxOccurs="unbounded"/>
        </xsd:complexType>
    </xsd:element>

    <!-- Collection Elements 集合元素-->
    <xsd:group name="collectionElements">
        <xsd:sequence>
            <xsd:element ref="description" minOccurs="0"/>
            <xsd:choice minOccurs="0" maxOccurs="unbounded">
                <xsd:element ref="bean"/>
                <xsd:element ref="ref"/>
                <xsd:element ref="idref"/>
                <xsd:element ref="value"/>
                <xsd:element ref="null"/>
                <xsd:element ref="array"/>
                <xsd:element ref="list"/>
                <xsd:element ref="set"/>
                <xsd:element ref="map"/>
                <xsd:element ref="props"/>
                <xsd:any namespace="##other" processContents="strict" minOccurs="0" maxOccurs="unbounded"/>
            </xsd:choice>
        </xsd:sequence>
    </xsd:group>

    <!--array数组:
        array可以包含多个内部bean, ref, collection, 或者value元素。
        该配置元素总是会产生一个数组,即使被定义为值类型映射的值。
    -->
    <xsd:element name="array">
        <xsd:annotation>
            <xsd:documentation><![CDATA[
	An array can contain multiple inner bean, ref, collection, or value elements.
	This configuration element will always result in an array, even when being
	defined e.g. as a value for a map with value type Object.
			]]></xsd:documentation>
        </xsd:annotation>
        <xsd:complexType>
            <xsd:complexContent>
                <xsd:extension base="listOrSetType">
                    <xsd:attribute name="merge" default="default" type="defaultable-boolean">
                        <xsd:annotation>
                            <xsd:documentation><![CDATA[
	Enables/disables merging for collections when using parent/child beans.
							]]></xsd:documentation>
                        </xsd:annotation>
                    </xsd:attribute>
                </xsd:extension>
            </xsd:complexContent>
        </xsd:complexType>
    </xsd:element>

    <!--list:
            list可以包含多个内部bean或值元素;
            list也可以映射一个数组类型。但需要进行必要的类型转换。
        merge:使用父/子bean时启用/禁用合并集合。
    -->
    <xsd:element name="list">
        <xsd:annotation>
            <xsd:documentation><![CDATA[
	A list can contain multiple inner bean, ref, collection, or value elements.
	A list can also map to an array type; the necessary conversion is performed
	automatically.
			]]></xsd:documentation>
        </xsd:annotation>
        <xsd:complexType>
            <xsd:complexContent>
                <xsd:extension base="listOrSetType">
                    <xsd:attribute name="merge" default="default" type="defaultable-boolean">
                        <xsd:annotation>
                            <xsd:documentation><![CDATA[
	Enables/disables merging for collections when using parent/child beans.
							]]></xsd:documentation>
                        </xsd:annotation>
                    </xsd:attribute>
                </xsd:extension>
            </xsd:complexContent>
        </xsd:complexType>
    </xsd:element>

    <!--set:set集合可以包含多个内部bean, ref引用,集合,或值元素-->
    <xsd:element name="set">
        <xsd:annotation>
            <xsd:documentation><![CDATA[
	A set can contain multiple inner bean, ref, collection, or value elements.
			]]></xsd:documentation>
        </xsd:annotation>
        <xsd:complexType>
            <xsd:complexContent>
                <xsd:extension base="listOrSetType">
                    <xsd:attribute name="merge" default="default" type="defaultable-boolean">
                        <xsd:annotation>
                            <xsd:documentation><![CDATA[
	Enables/disables merging for collections when using parent/child beans.
							]]></xsd:documentation>
                        </xsd:annotation>
                    </xsd:attribute>
                </xsd:extension>
            </xsd:complexContent>
        </xsd:complexType>
    </xsd:element>


    <!--map:从一个key到特定对象的映射。映射可以是空的 。-->
    <xsd:element name="map">
        <xsd:annotation>
            <xsd:documentation><![CDATA[
	A mapping from a key to an object. Maps may be empty.
			]]></xsd:documentation>
        </xsd:annotation>
        <xsd:complexType>
            <xsd:complexContent>
                <xsd:extension base="mapType">
                    <xsd:attribute name="merge" default="default" type="defaultable-boolean">
                        <xsd:annotation>
                            <xsd:documentation><![CDATA[
	Enables/disables merging for collections when using parent/child beans.
							]]></xsd:documentation>
                        </xsd:annotation>
                    </xsd:attribute>
                </xsd:extension>
            </xsd:complexContent>
        </xsd:complexType>
    </xsd:element>

    <!--entry:一个map entry可以是内部bena, ref引用,value, 或集合。
               key属性或子元素提供key
    -->
    <xsd:element name="entry" type="entryType">
        <xsd:annotation>
            <xsd:documentation><![CDATA[
	A map entry can be an inner bean, ref, value, or collection.
	The key of the entry is given by the "key" attribute or child element.
			]]></xsd:documentation>
        </xsd:annotation>
    </xsd:element>

    <!--props与map的不同是,props的值一定是strings, props可以是空-->
    <xsd:element name="props">
        <xsd:annotation>
            <xsd:documentation><![CDATA[
	Props elements differ from map elements in that values must be strings.
	Props may be empty.
			]]></xsd:documentation>
        </xsd:annotation>
        <xsd:complexType>
            <xsd:complexContent>
                <xsd:extension base="propsType">
                    <xsd:attribute name="merge" default="default" type="defaultable-boolean">
                        <xsd:annotation>
                            <xsd:documentation><![CDATA[
	Enables/disables merging for collections when using parent/child beans.
							]]></xsd:documentation>
                        </xsd:annotation>
                    </xsd:attribute>
                </xsd:extension>
            </xsd:complexContent>
        </xsd:complexType>
    </xsd:element>

    <!--key元素可以包含内部bean, ref, value, collection-->
    <xsd:element name="key">
        <xsd:annotation>
            <xsd:documentation><![CDATA[
	A key element can contain an inner bean, ref, value, or collection.
			]]></xsd:documentation>
        </xsd:annotation>
        <xsd:complexType>
            <xsd:group ref="collectionElements"/>
        </xsd:complexType>
    </xsd:element>

    <!--属性的字符串值。注意空格将会被删除,以避免特定xml格式化所不需要的空格 -->
    <xsd:element name="prop">
        <xsd:annotation>
            <xsd:documentation><![CDATA[
	The string value of the property. Note that whitespace is trimmed
	off to avoid unwanted whitespace caused by typical XML formatting.
			]]></xsd:documentation>
        </xsd:annotation>
        <xsd:complexType mixed="true">
            <xsd:choice minOccurs="0" maxOccurs="unbounded"/>
            <xsd:attribute name="key" type="xsd:string" use="required">
                <xsd:annotation>
                    <xsd:documentation><![CDATA[
	The key of the property entry.
					]]></xsd:documentation>
                </xsd:annotation>
            </xsd:attribute>
        </xsd:complexType>
    </xsd:element>

    <!--propertyType:
            name: property的名称,遵循javabean命名约定
            ref:<ref bean="" 的简写
            value: <value><?value>的缩写

    -->
    <xsd:complexType name="propertyType">
        <xsd:sequence>
            <xsd:element ref="description" minOccurs="0"/>
            <xsd:choice minOccurs="0" maxOccurs="1">
                <xsd:element ref="meta"/>
                <xsd:element ref="bean"/>
                <xsd:element ref="ref"/>
                <xsd:element ref="idref"/>
                <xsd:element ref="value"/>
                <xsd:element ref="null"/>
                <xsd:element ref="array"/>
                <xsd:element ref="list"/>
                <xsd:element ref="set"/>
                <xsd:element ref="map"/>
                <xsd:element ref="props"/>
                <xsd:any namespace="##other" processContents="strict"/>
            </xsd:choice>
        </xsd:sequence>
        <xsd:attribute name="name" type="xsd:string" use="required">
            <xsd:annotation>
                <xsd:documentation><![CDATA[
	The name of the property, following JavaBean naming conventions.
				]]></xsd:documentation>
            </xsd:annotation>
        </xsd:attribute>
        <xsd:attribute name="ref" type="xsd:string">
            <xsd:annotation>
                <xsd:documentation><![CDATA[
	A short-cut alternative to a nested "<ref bean='...'/>".
				]]></xsd:documentation>
            </xsd:annotation>
        </xsd:attribute>
        <xsd:attribute name="value" type="xsd:string">
            <xsd:annotation>
                <xsd:documentation><![CDATA[
	A short-cut alternative to a nested "<value>...</value>" element.
				]]></xsd:documentation>
            </xsd:annotation>
        </xsd:attribute>
    </xsd:complexType>

    <!-- Collection Types -->

    <!--collectionType:
        value-type:默认的嵌套值的java类型,必须是全类名
    -->
    <!-- base type for collections that have (possibly) typed nested values -->
    <xsd:complexType name="collectionType">
        <xsd:attribute name="value-type" type="xsd:string">
            <xsd:annotation>
                <xsd:documentation source="java:java.lang.Class"><![CDATA[
	The default Java type for nested values. Must be a fully qualified
	class name.
				]]></xsd:documentation>
            </xsd:annotation>
        </xsd:attribute>
    </xsd:complexType>

    <!-- 'list' and 'set' collection type -->
    <xsd:complexType name="listOrSetType">
        <xsd:complexContent>
            <xsd:extension base="collectionType">
                <xsd:group ref="collectionElements"/>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>

    <!-- 'map' element type -->
    <!--map类:
        key-type:默认的嵌套key的java类型。必须是全类名。
    -->
    <xsd:complexType name="mapType">
        <xsd:complexContent>
            <xsd:extension base="collectionType">
                <xsd:sequence>
                    <xsd:element ref="description" minOccurs="0"/>
                    <xsd:choice minOccurs="0" maxOccurs="unbounded">
                        <xsd:element ref="entry"/>
                    </xsd:choice>
                </xsd:sequence>
                <xsd:attribute name="key-type" type="xsd:string">
                    <xsd:annotation>
                        <xsd:documentation source="java:java.lang.Class"><![CDATA[
	The default Java type for nested entry keys. Must be a fully qualified
	class name.
						]]></xsd:documentation>
                    </xsd:annotation>
                </xsd:attribute>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>

    <!-- 'entry' element type -->
    <!--entry:
        key;每个map元素都必须在其属性或子元素中声明key。key属性常常时string
        key-ref:<ref bean=""/>的简写
        value:<value>...</value>的简写
        value-ref:<ref bean='...'/>的简写
        value-type: 简写替代内嵌的<value type='...' >...</value>中type属性
    -->
    <xsd:complexType name="entryType">
        <xsd:sequence>
            <xsd:element ref="key" minOccurs="0"/>
            <xsd:group ref="collectionElements"/>
        </xsd:sequence>
        <xsd:attribute name="key" type="xsd:string">
            <xsd:annotation>
                <xsd:documentation><![CDATA[
	Each map element must specify its key as attribute or as child element.
	A key attribute is always a String value.
				]]></xsd:documentation>
            </xsd:annotation>
        </xsd:attribute>
        <xsd:attribute name="key-ref" type="xsd:string">
            <xsd:annotation>
                <xsd:documentation><![CDATA[
	A short-cut alternative to a to a "key" element with a nested
	"<ref bean='...'/>".
				]]></xsd:documentation>
            </xsd:annotation>
        </xsd:attribute>
        <xsd:attribute name="value" type="xsd:string">
            <xsd:annotation>
                <xsd:documentation><![CDATA[
	A short-cut alternative to a nested "<value>...</value>"
	element.
				]]></xsd:documentation>
            </xsd:annotation>
        </xsd:attribute>
        <xsd:attribute name="value-ref" type="xsd:string">
            <xsd:annotation>
                <xsd:documentation><![CDATA[
	A short-cut alternative to a nested "<ref bean='...'/>".
				]]></xsd:documentation>
            </xsd:annotation>
        </xsd:attribute>
        <xsd:attribute name="value-type" type="xsd:string">
            <xsd:annotation>
                <xsd:documentation><![CDATA[
	A short-cut alternative to a 'type' attribute on a nested
	"<value type='...' >...</value>" element.
				]]></xsd:documentation>
            </xsd:annotation>
        </xsd:attribute>
    </xsd:complexType>

    <!-- 'props' collection type -->
    <xsd:complexType name="propsType">
        <xsd:complexContent>
            <xsd:extension base="collectionType">
                <xsd:sequence>
                    <xsd:choice minOccurs="0" maxOccurs="unbounded">
                        <xsd:element ref="prop"/>
                    </xsd:choice>
                </xsd:sequence>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>

    <!-- simple internal types -->
    <xsd:simpleType name="defaultable-boolean">
        <xsd:restriction base="xsd:NMTOKEN">
            <xsd:enumeration value="default"/>
            <xsd:enumeration value="true"/>
            <xsd:enumeration value="false"/>
        </xsd:restriction>
    </xsd:simpleType>

</xsd:schema> 

下面我们自定义schema及相应的NamesepaceHandler来扩展Spring:

<?xml version="1.0" encoding="UTF-8" ?>
<xsd:schema xmlns="http://www.miracle.com/entity/schema/people"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns:beans="http://www.springframework.org/schema/beans"
            targetNamespace="http://www.miracle.com/entity/schema/people"
            elementFormDefault="qualified"
            attributeFormDefault="unqualified">

    <!--注意这里需要引入spring beans的名称空间, 从而使用base="beans:identifiedType"-->
    <xsd:import namespace="http://www.springframework.org/schema/beans" />
    <!--定义了一个名称为people的元素,它含有两个属性, name和age
        注意:引入了spring beans名称控件,使用了spring的base扩展后,这里会默认引入id属性
    -->
    <!--
        我们可以看一下identifiedType中的内容:其实就是一个包含了名为id的属性
        <xsd:complexType name="identifiedType" abstract="true">
            <xsd:attribute name="id" type="xsd:string">
        </xsd:attribute>
    </xsd:complexType>
    -->

    <xsd:element name="people">
        <xsd:complexType>
            <xsd:complexContent>
                <xsd:extension base="beans:identifiedType">
                    <xsd:attribute name="name" type="xsd:string" />
                    <xsd:attribute name="age" type="xsd:int" />
                </xsd:extension>
            </xsd:complexContent>
        </xsd:complexType>
    </xsd:element>

</xsd:schema>

编写实体类(省略:注意实体类应该有三个属性:id,name和age)和BeanDefinitionParser以及BeanNamespaceHandler:

package com.spring.xml;

import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.w3c.dom.Element;

public class PeopleBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {

    @Override
    protected Class<?> getBeanClass(Element element) {
        return People.class;
    }

    @Override
    protected void doParse(Element element, BeanDefinitionBuilder builder) {

        String id = element.getAttribute("id");
        String name = element.getAttribute("name");
        String age = element.getAttribute("age");
        System.out.println(element.getNodeName());

        builder.addPropertyValue("id", id).addPropertyValue("name", name).addPropertyValue("age", age);
    }
}
package com.spring.xml;

import org.springframework.beans.factory.xml.NamespaceHandlerSupport;

public class PeopleNameSpaceHandler extends NamespaceHandlerSupport {
    @Override
    public void init() {

        registerBeanDefinitionParser("people", new PeopleBeanDefinitionParser());
    }
}

application.xml配置文件及测试类:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:entity="http://www.miracle.com/entity/schema/people"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.miracle.com/entity/schema/people http://www.miracle.com/entity/schema/people.xsd">
    <!-- 注意这里的id必须提供,它是bean在容器中的唯一标识,如果不提供则容器会抛出异常 -->
    <entity:people id="people" name="123" age="123"/>

</beans>
package com.spring.xml;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.Arrays;

public class PeopleTest {


    @Test
    public void test() {

        ApplicationContext ioc = new ClassPathXmlApplicationContext("application.xml");
        People people = (People) ioc.getBean("people");

        String[] beanDefinitionNames = ioc.getBeanDefinitionNames();
        System.out.println(Arrays.asList(beanDefinitionNames));
        System.out.println(people);
    }
}

基本的spring schema文件分析就到这里了。
原本的计划是写一个比较复杂的自定义schema出来,但因为写的过程中出现了很多异常,所以决定暂时放弃,后续再来补充。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值