`
yiliner
  • 浏览: 214515 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

XML Schema学习笔记和注解-(转)

    博客分类:
  • GMF
XML 
阅读更多

XML Schema学习笔记和注解-(转)

1、复杂型和简单型之间最根本的区别就是:复杂型的内容中可以包含其他元素,也可以带有属性(Attribute),但简单型既不能包含子元素,也不能带有任何属性,但限制条件或扩展条件还是可以有的。

一个复杂类型例子:
<xsd:complexType >
    <xsd:sequence>
        <xsd:element name="name"type="xsd:string"/>
        <xsd:element type="xsd:string"/>
        <xsd:element type="xsd:string"/>
        <xsd:element type="xsd:decimal"/>
    </xsd:sequence>
    <xsd:attribute name="country" type="xsd:NMTOKEN" fixed="US"/>
</xsd:complexType>

一个简单类型例子:
<xsd:simpleType >
    <xsd:restriction base="xsd:integer">
        <xsd:minInclusive value="10000"/>
        <xsd:maxInclusive value="99999"/>
    </xsd:restriction>
</xsd:simpleType> 


2、element存在约束:element可以通过其minOccurs和maxOccurs两个属性来约束元素实例存在的个数,这两个属性的缺省值都是1,表示默认情况下此元素在XML实例文档中必须出现一次。
例如:
<element minOccurs="1" maxOccurs="1" type="timeInstant"/>

3、attribute存在约束:元素属性也可以通过attribute的use属性来约束出现一次或根本不出现;use属性的取值可以是required,optional,prohibited三个值,缺省(默认)值是optional. 


4、 element和attribute都有一个default和fixed属性,不能同时存在。针对element来说,只有当element实例为空时才采用此 default值,而attribute是当实例不提供此attribute时才采用此default值,因此对attribute而言,只有其use值是optional时default值才有意义,而且对element和attribute来说fixed和default两个属性不能同时存在,否则会出现错误。 
fixed属性要求element或attribute如果出现的话,就一定要是fixed属性里指定的值。


5、全局元素和全局属性。直接定义在schema元素下,即schema元素的顶级子元素的element和attribute都是全局的,称之为全局元素和全局属性,你在其他
型定义中可以直接引用。 


  <xsd:annotation>
    <xsd:documentation xml:lang="en">
     Purchase order schema for Example.com.
     Copyright 2000 Example.com. All rights reserved.
    </xsd:documentation>
  </xsd:annotation>

  <xsd:element  type="PurchaseOrderType"/>

  <xsd:element  type="xsd:string"/>

  <xsd:complexType >
    <xsd:sequence>
      <xsd:element  type="USAddress"/>
      <xsd:element  type="USAddress"/>
      <xsd:element ref="comment" minOccurs="0"/>
      <xsd:element   type="Items"/>
    </xsd:sequence>
    <xsd:attribute  type="xsd:date"/>
  </xsd:complexType>

  <xsd:complexType >
    <xsd:sequence>
      <xsd:element    type="xsd:string"/>
      <xsd:element  type="xsd:string"/>
      <xsd:element    type="xsd:string"/>
      <xsd:element   type="xsd:string"/>
      <xsd:element     type="xsd:decimal"/>
    </xsd:sequence>
    <xsd:attribute  type="xsd:NMTOKEN"
                   fixed="US"/>
  </xsd:complexType>

  <xsd:complexType >
    <xsd:sequence>
      <xsd:element  minOccurs="0" maxOccurs="unbounded">
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element  type="xsd:string"/>
            <xsd:element >
              <xsd:simpleType>
                <xsd:restriction base="xsd:positiveInteger">
                  <xsd:maxExclusive value="100"/>
                </xsd:restriction>
              </xsd:simpleType>
            </xsd:element>
            <xsd:element   type="xsd:decimal"/>
            <xsd:element ref="comment"   minOccurs="0"/>
            <xsd:element  type="xsd:date" minOccurs="0"/>
          </xsd:sequence>
          <xsd:attribute  type="SKU" use="required"/>
        </xsd:complexType>
      </xsd:element>
    </xsd:sequence>
  </xsd:complexType>

  <!-- Stock Keeping Unit, a code for identifying products -->
  <xsd:simpleType >
    <xsd:restriction base="xsd:string">
      <xsd:pattern value="\d{3}-[A-Z]{2}"/>
    </xsd:restriction>
  </xsd:simpleType>
</xsd:schema>

从上面这个例子可以看出,purchaseOrder和comment是全局元素,可以被其他element用ref属性引用,purchaseOrderType,USAddress,Items和SKU是全局属性,可以被其他element用type属性引用。

6、派生新型有两种方式:第一种就是直接从其他
型中扩展(继承)而来,另外一种就是通过对已有型进行限定性约束而来。 
如:以下有三种通过限定性约束定义的新
型: 
通过值范围限定: 
<xsd:simpleType >
    <xsd:restriction base="xsd:integer">
        <xsd:minInclusive value="10000"/>
        <xsd:maxInclusive value="99999"/>
    </xsd:restriction>
</xsd:simpleType> 
使用模式匹配限定: 
<xsd:simpleType >
    <xsd:restriction base="xsd:string">
        <xsd:pattern value="\d{3}-[A-Z]{2}"/>
    </xsd:restriction>
</xsd:simpleType> 
使用枚举方式限定: 
<xsd:simpleType >
    <xsd:restriction base="xsd:string">
        <xsd:enumeration value="BeiJing"/>
        <xsd:enumeration value="NanChang"/>
        <xsd:enumeration value="ShangHai"/>
    </xsd:restriction>
</xsd:simpleType> 

7、原子型(不可分割的型,象string,integer等系统内建的型)、列表型、联合型合起来统一称为简单型。在Schema中有NMTOKENS、IDREFS、ENTITIES三种内建的列表
型,你也可以从已有的简单型来创建list(列表)型,但你不能从已有的list型和复杂型来创建列表(list)型。 
如: 
<xsd:simpleType >
    <xsd:list itemType="myInteger"/>
</xsd:simpleType> 
在XML实例文档中列表
型的值是通过空格来进行分隔的,如果声明了一个listOfMyIntType元素,其值可能是: 
<listOfMyInt>20003 15037 95977 95945</listOfMyInt> 

8、约束List类型。有几个方面的元素可以应用于list
型来进行约束,它们是:length、minLength、maxLength和enumeration,如: 
<xsd:simpleType >
    <xsd:list itemType="USState"/>
</xsd:simpleType>
<xsd:simpleType >
    <xsd:restriction base="USStateList">
        <xsd:length value="6"/>
    </xsd:restriction>
</xsd:simpleType> 
注:针对列表
型要千万注意成员是string型的,因为string型中的空格和列表型的分割符空格会造成部分混淆。

9、对元素的定义可以采用通过指定其type属性为已定义的属性的方式(基本类型或自定义的全局属性),也可一采用匿名定义型的方式,如: 
采用
型定义: 
<xsd:element name=”comment” type=”xsd:string”> 
采用匿名定义: 
<xsd:element
    <xsd:simpleType>
        <xsd:restriction base=”xsd:positiveInteger”>
            <xsd:maxExclusive value=”100” />
        </xsd:restriction>
    </xsd:simpleType>
</xsd:element> 

10、union(联合)表示在XML实例文档中的元素实例符合union
型定义的成员型中的一种就可以了(合法),这一点和C++中的联合型有似的概念,如: 
<xsd:simpleType >
    <xsd:union memberTypes="xsd:string integer"/>
</xsd:simpleType> 

11、复杂型一般可以分为三
第一
是包含字符内容和属性但不包含子元素,针对第一可以通过simpleContent来实现;
第二
是包含属性和子元素但不包含字符数据(字符数据包含在子元素中),通过complexContent来做到;
第三
是即包含属性和字符内容又包含子元素的,只需要将complexType的属性mixed设为true就可以了;
具体的例子如下: 

第一种
型(从一个简单型扩展而来,增加了属性): 
<xsd:element >
    <xsd:complexType>
        <xsd:simpleContent>
            <xsd:extension base="xsd:decimal">
                <xsd:attribute type="xsd:string"/>
            </xsd:extension>
        </xsd:simpleContent>
    </xsd:complexType>
</xsd:element> 

第二种
型(有一个element和两个attribute构成): 
<xsd:element >
    <xsd:complexType>
        <xsd:complexContent>
            <xsd:element ?type=”xsd:string” />
            <xsd:attribute type="xsd:string"/>
            <xsd:attribute ?type="xsd:decimal"/>
        </xsd:complexContent>
    </xsd:complexType>
</xsd:element> 
注意:在这里由于默认情况下缺省是complexContent,所以在这里简略的写法是: 
<xsd:element >
    <xsd:complexType>
        <xsd:element />
        <xsd:attribute type="xsd:string"/>
        <xsd:attribute ?type="xsd:decimal"/>
    </xsd:complexType>
</xsd:element> 

第三种
型: 
<xsd:element >
    <xsd:complexType mixed="true">
        <xsd:sequence>
            <xsd:element >
                <xsd:complexType mixed="true">
                    <xsd:sequence>
                        <xsd:element type="xsd:string"/>
                    </xsd:sequence>
                </xsd:complexType>
            </xsd:element>
            <xsd:element type="xsd:positiveInteger"/>
            <xsd:element type="xsd:string"/>
            <xsd:element type="xsd:date" minOccurs="0"/>
        </xsd:sequence>
    </xsd:complexType>
</xsd:element> 
第三种
型的实例可能如下: 
<letterBody>
    <salutation>Dear Mr.
    <name>Robert Smith</name>.
    </salutation>
    Your order of
    <quantity>1</quantity>
    <productName>Baby Monitor</productName>
    shipped from our warehouse on
    <shipDate>1999-05-21</shipDate>
</letterBody>

12、根据11的描述那么要定义一个空内容的元素,也就是说定义一个只包含属性的元素,只要在complexContent中不包含任何子元素,就可以了,如(注:complexContent在complexType外面被省略了):
<xsd:element >
    <xsd:complexType>
        <xsd:attribute type="xsd:string"/>
        <xsd:attribute type="xsd:decimal"/>
    </xsd:complexType>
</xsd:element>

13、anyType是所有Schema型的基型,和Java中的Object似。因此,以下定义: 
<xsd:element name="anything" type="xsd:anyType"/> 
可以写成: 
<xsd:element name="anything"/> 

14、Schema中用annotation、document、appInfo三个元素来进行注释,其中appI和document都是作为annotation的子元素来处理的。并且annotation一般是作为schema的顶层子元素、element的构造、型定义的顶层子元素的。 
如: 
<xsd:element >
    <xsd:annotation>
        <xsd:documentation xml:lang="en">
            element declared with anonymous type
        </xsd:documentation>
    </xsd:annotation>
    <xsd:complexType>
        <xsd:annotation>
            <xsd:documentation xml:lang="en">
                empty anonymous type with 2 attributes
            </xsd:documentation>
        </xsd:annotation>
        <xsd:complexContent>
            <xsd:restriction base="xsd:anyType">
                <xsd:attribute type="xsd:string"/>
                <xsd:attribute type="xsd:decimal"/>
            </xsd:restriction>
        </xsd:complexContent>
    </xsd:complexType>
</xsd:element> 

15、 choice,all
choice仅允许在实例文档中使用其中一个子元素;在all中的所有元素都可以出现一次或一次都不出现,并且其中元素实例是没有顺序约束的,而且all 必须放在任何内容模型的最顶层,为了说明这个问题,下面先列出一个合法的,然后列出一个不合法的以供对照说明: 
<xsd:complexType >
    <xsd:all>
        <xsd:element type="USAddress"/>
        <xsd:element type="USAddress"/>
        <xsd:element ref="comment" minOccurs="0"/>
        <xsd:element type="Items"/>
    </xsd:all>
    <xsd:attribute type="xsd:date"/>
</xsd:complexType> 
下面是一个不合法的: 
<xsd:complexType >
    <xsd:sequence>
        <xsd:all>
            <xsd:element type="USAddress"/>
            <xsd:element type="USAddress"/>
            <xsd:element type="Items"/>
        </xsd:all>
        <xsd:sequence>
            <xsd:element ref="comment" />
        </xsd:sequence>
    </xsd:sequence>
    <xsd:attribute type="xsd:date"/>
</xsd:complexType>

 

16、attributeGroup属性组。在存在很多型中都有几个相同的型的情况,可以采用属性组的方式来进行重用,属性组定义的格式是: 
<xsd:attributeGroup
    <xsd:attribute type=”xsd:string” />
    <xsd:attribute type=”xsd:string” />
    …
</xsd:attributeGroup> 

使用可以采用以下方式: 
<xsd:element
    <xsd:comlexType>
        <xsd:element />
        <xsd:attributeGroup ref=”attrGroupName” />
    </xsd:complexType>
</xsd:element> 

17、关于include的用法 
include元素可以将外部的定义和声明引入到文档中,并且作为新Schema文档的一部分,但必须注意的一点是,被包含成员的目标命名空间TargetNamespace必须和包含的目标命名空间schemaLocation一样。具体写法例子是: 
<include schemaLocation=“http://www.example.com/schemas/address.xsd” /> 

18、extension。如果一个
型是从另一个型扩展而来的,那么定义为父型的element,在实例文档中,可以通过符合子型的element实例来代替,但必须通过xsi:type指明此元素的具体型。例如: 
<xsd:complexType
    <xsd:sequence>
        <xsd:element type=”xsd:string” />
        <xsd:element type=”xsd:string” />
    </xsd:sequence>
</xsd:complexType> 
<!-- 扩展
型定义 --> 
<xsd:complexType
    <complexContent>
        <xsd:extension base=”Person”>
            <xsd:sequence>
            <xsd:element
                <xsd:restriction base=”string”>
                    <xsd:enumeration value=”male” />
                </xsd:restriction>
            </xsd:element>
            </xsd:sequence>
        </xsd:extension>
    </complexContent>
</xsd:complexType>
<!-- 
型的声明 --> 
<xsd:element name=”human” type=”Person” /> 
在XML实例文档中针对human可以是这样的(和面向对象有
似的概念): 
<human xsi:type=”Father”>
    <name>xiaogen</name>
    <gender>male</gender>
</human> 
19、关于置换组 substituionGroup
XML Schema 提供了一种机制叫置换组,允许原先定义好的元素被其他元素所替换。更明确的,这个置换组包含了一系列的元素,这个置换组中的每一个元素都被定义为可以替换一个指定的元素,这个指定的元素称为头元素(Head Element),需要注意的是头元素必须作为全局元素声明,注意,当一个实例文档包含置换元素时替换元素的
型时从它们的头元素那里派生的,此时并不需要使用我们前面所说的xsi:type来识别这些被派生的型,当定义了置换组之后,并非意味着不能使用头元素,而只能使用这个置换组中的元素,它只是提供了一个允许元素可替换使用的机制。例如: 
<xsd:schema>
    <xsd:element type=”xsd:string”/>
    <xsd:element type=”xsd:string” substitutionGroup=”comment” />
    <xsd:element type=”xsd:string” substituionGroup=”comment” />
    <xsd:element
        <xsd:complexType>
            <xsd:element type=”xsd:string” />
            <xsd:element type=”xsd:decimal” />
            <xsd:element ref=”comment” />
            <xsd:element type=”xsd:date” />
        </xsd:complexType>
    </xsd:element>
</xsd:schema> 
下面是实例文档的一个例子: 
<order>
    <productName>Lapis necklace</productName>
    <price>999</price>
    <shipComment>Use gold wrap if possible</shipComment>
    <customerComment>Want this for the holidays!</customerComment>
    <shipDate>2004-08-15</shipDate>
</order> 

20、抽象元素和抽象型 
当一个元素或者型被声明为“abstract”时,那么它就不能在实例文档中使用。当一个元素被声明为”abstract”的时候,元素的置换组的成员必须出现在实例文档中。当一个元素相应的型被定义声明为"abstract"时,所有关联该元素的实例必须使用"xsi:type"来指明一个型,这个型必须是非抽象的,同时是在定义中声明的抽象型的派生型。 
一、如将上面的comment元素的声明更改成: 
<xsd:element name=”comment” type=”xsd:string” abstract=”true” /> 
那么上面的order实例中就只能包含customerComment和shipComment才是有效的。 
二、如果有下面的
型定义: 
<schema xmlns="http://www.w3.org/2001/XMLSchema"  targetNamespace="http://cars.example.com/schema"  xmlns:target="http://cars.example.com/schema"> 
    <complexType abstract="true"/> 
    <complexType > 
        <complexContent>
            <extension base="target:Vehicle"/>
        </complexContent>
    </complexType>
    <complexType > 
        <complexContent>
            <extension base="target:Vehicle"/>
        </complexContent>
    </complexType>
    <element type="target:Vehicle"/> 
</schema> 
根据以上的定义和声明,下面的实例片断就是不能通过验证的: 
<transport 
xmlns="http://cars.example.com/schema" /> 
下面经过修改的就可以通过验证了。 
<transport 
xmlns=“http://cars.example.com/schema”  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Car"/> 

21、Final。为了阻止
型被派生(包括通过限制派生和通过扩展派生),可以使用final来设置(有点和java中的final的概念似),其值有三个:restriction,extension,#all。在模式文件的根元素schema元素中有一个可选的finalDefault属性,它的值能够取为final属性所允许的几个值之一。指定finalDefault属性的值的效果等于在模式文档中每个型定义和元素声明中指定final属性,同时其值为finalDefault属性的值。如果想阻止前面的Person被限制派生,我们需要修改定义为如下: 
<xsd:complexType final=”restriction”>
    <xsd:sequence>
        <xsd:element type=”xsd:string” />
        <xsd:element type=”xsd:string” />
    </xsd:sequence>
</xsd:complexType> 

22、block。因为在实例文档中与父
型关联的元素(也就是声明为父型的元素)可以通过派生的子型来替代,这在2中已经有详细的说明和例子。同时,XML Schema也提供了一种机制来控制派生型以及置换组在实例文档中使用的机制。这种机制是通过型的block属性来控制的,该属性可以取值为:restriction,extension,#all。和final属性一样,在模式文档的根元素 schema元素里有一个可选的属性blockDefault,它的值为block属性所允许的值中的一个。指定blockDefault属性的作用等价于在模式文档中为每个型定义和元素声明指定block属性。如在前面例子中我们想阻止在使用Father来替代Person的话我们需要修改Person的定义如下: 
<xsd:complexType block=”extension”>
    <xsd:sequence>
        <xsd:element type=”xsd:string” />
        <xsd:element type=”xsd:string” />
    </xsd:sequence>
</xsd:complexType> 
取值为“extension”的block属性将阻止在实例文档中使用通过扩展的派生
型来替换Person(即可以阻止Father来替换Person),然而它不会阻止通过约束的派生来替换Person。 

23、用fixed禁止派生。另外一种派生
型的控制机制是应用于简单型方面的派生。当定义一个简单型的时候,我们可以使用fixed属性对它的所有定义的参数进行修饰,以阻止这些参数在型派生中被修改,例如: 
<xsd:simpleType
    <xsd:restriction base=”xsd:string”>
        < xsd:length value=”7” fixed=”true” />
    </xsd:restriction>
</xsd:simpleType> 
当这个简单
型被定义之后,我们能够派生出一个新的邮编型,在其中我们使用了一个没有在基本型中固定的参数: 
<xsd:simpleType >
    <xsd:restriction base=" Postcode">
        <xsd:pattern value="[A-Z]{2}\d\s\d[A-Z]{2}"/>
    </xsd:restriction>
</xsd:simpleType> 
然而,我们不能购派生出一个这样的新的邮编
型:在其中我们重新定义了任何在基型中已经被固定(fixed)的参数: 
<xsd:simpleType >
    <xsd:restriction base="ipo:Postcode">
        <xsd:pattern value="[A-Z]{2}\d\d[A-Z]{2}"/>
        <!-- illegal attempt to modify facet fixed in base type --> 
        <xsd:length value="6" fixed="true"/>
    </xsd:restriction>
</xsd:simpleType>

评论

相关推荐

    《Jaxb2 转换XML文档》学习笔记

    在处理包含命名空间的XML时,JAXB2提供`@XmlSchema`和`@XmlElementNamespace`等注解来处理命名空间前缀和URI。 8. **自定义转换** 当默认的映射机制不满足需求时,可以通过实现`XmlAdapter`接口来创建自定义的...

    Spring学习笔记(16)----使用Spring配置文件实现AOP

    在本篇Spring学习笔记中,我们将深入探讨如何利用Spring配置文件来实现面向切面编程(AOP)。面向切面编程是Spring框架的核心特性之一,它允许我们把关注点分离,将横切关注点(如日志、事务管理、权限控制等)与...

    Spring MVC 学习笔记 一 创建项目

    更多关于Spring MVC的高级特性,如拦截器、AOP、MVC注解、数据绑定等,将在后续的学习笔记中逐步展开。参考提供的博文链接(https://starscream.iteye.com/blog/1057305)可以获取更多详细信息和实战案例。

    Spring2.5.6学习笔记-最新

    以上是 Spring 2.5.6 学习笔记中的关键知识点,通过这些基础知识的学习,开发者可以开始构建基于 Spring 框架的应用程序。接下来,可以进一步深入学习 Spring 的高级特性,如事务管理、安全性、Web 开发等方面的知识...

    张龙S2SH学习笔记(经典)

    【张龙S2SH学习笔记(经典)】是基于圣思园张龙的视频教程整理出的学习资料,主要涵盖了Struts2、Spring和Hibernate这三大框架的整合使用,也就是我们常说的SSH(Spring、Struts2、Hibernate)框架集成。SSH框架在...

    JPA的学习笔记(java注解,事物)

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0"&gt; ...

    尚硅谷Webservice学习笔记

    综上所述,尚硅谷的Web Service学习笔记涵盖了XML Schema、HTTP协议基础以及Web Service的核心概念和应用,为深入理解和实践Web Service提供了基础知识。要了解更多关于Web Service的详细内容,可以通过指定的学习...

    hibernate注解学习笔记

    ### Hibernate注解学习笔记 #### 一、简介与概述 Hibernate是Java领域内最流行的ORM(Object Relational Mapping)框架之一,它通过提供强大的映射工具和服务,将面向对象的数据模型(即Java类)与传统的关系型...

    Spring MVC 学习笔记

    **Spring MVC 学习笔记** Spring MVC 是 Spring 框架的一个模块,专门用于构建 Web 应用程序。它提供了一种模型-视图-控制器(MVC)架构,简化了开发过程,使得开发者可以专注于业务逻辑而不必过于关注底层的细节。...

    超详细的springboot学习笔记

    ### Spring Boot 学习笔记概览 #### 一、Spring 的发展历程 1. **Spring 1.x 时代:** - 在Spring框架发展的初期(即Spring 1.x时代),主要采用XML作为配置文件来管理Bean的声明周期。这种方式在项目规模较小的...

    JAXB 学习笔记

    **JAXB(Java Architecture for XML Binding)学习笔记** JAXB是Java平台标准版(Java SE)的一部分,它提供了一种方便的方式来将XML数据绑定到Java对象上,以及将Java对象转换为XML数据。这个强大的工具使得开发...

    Spring学习笔记

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=...

    Spring3 MVC 学习笔记 入门

    ### Spring3 MVC 学习笔记入门知识点解析 #### 一、Spring MVC 概念与架构 **Spring MVC** 是 Spring Framework 的一个重要模块,主要用于构建基于 Web 的应用。它实现了 Model-View-Controller(MVC)设计模式,...

    jpa学习笔记

    ### JPA 学习笔记详解 #### 一、JPA 概述 Java Persistence API (JPA) 是 Sun 公司提出的一种 Java 持久层标准,它为 Java 开发者提供了一种对象关系映射 (ORM) 的工具来管理 Java 应用程序中的关系型数据。JPA ...

    springMVC学习笔记

    ### SpringMVC学习笔记 #### 一、SpringMVC概述 **1.1 什么是SpringMVC** SpringMVC作为Spring Framework的一个重要组成部分,主要针对Web应用开发提供了一个功能全面的MVC(Model-View-Controller)框架。它是...

    spring学习笔记

    ### Spring学习笔记知识点详解 #### 一、Spring理论基础 1. **依赖注入与控制反转** - **依赖注入(Dependency Injection, DI)**: 在软件工程中,依赖注入是一种设计模式,它允许对象在其生命周期中动态接收其依赖...

Global site tag (gtag.js) - Google Analytics