Spring自定义xml标签

来源:互联网 发布:设a是2n 1阶矩阵 编辑:程序博客网 时间:2024/06/10 14:36

1、总体思路:

1.1) 编写标签schema

1.2) 添加文件spring.schemasspring.handlers(目录固定在classpath:/META-INF下,被依赖代码必须打成一个jar包)

1.3) 编写一堆handler


2、详细说明

自定义的标签一定有属于自己的namespace,所以要有个namespaceHandler(继承NamespaceHandlerSupport),这个handler的作用就是注册自定义标签的parser,且该handler的全称必须写在spring.handlers里。



自定义标签也需要引入namespace,这个namespace全称及schema文件所在路径就写在spring.schemas文件里(与文件spring.handlers同目录)。



自定义的每一种标签都对应一个parser(实现接口BeanDefinitionParser)和beanClassparser就是从xmlelement中抽取相关信息,生成一个BeanDefinition(如GenericBeanDefinition)实例definition,并将beanClassbeanNamepropertyValue赋给definition,最后将definition注册到ParserContext里。

beanName可以调用spring提供的id生成器

String beanName = BeanDefinitionReaderUtils.generateBeanName(definition, parserContext.getRegistry());


这里的propertyValue是用来给新newbeanClass的成员字段赋值用的。propertyValue是一个ListList中每个成员(key是成员字段名,value是成员字段值类型此处是Object)都对应beanClass的一个成员字段。

这里的beanClass可以实现FactoryBeanInitializingBean来生成个性化的bean



FactoryBean有个接口public T getObject(){}spring在实例化完一个bean之后,判断下该bean是否实现了FactoryBean接口,如果实现了,那么调用下getObject()接口,以返回值作为真正的bean实例。

InitializingBean有个接口public void afterPropertiesSet()springnew一个bean对象,并且完成该对象的成员字段的赋值后,调用下该接口(注意getObject是在该接口之后才调用)。



3、使用自定义的xml标签

<beans    xmlns="http://www.springframework.org/schema/beans"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:sg="http://code.sample.com/schema/sg"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://code.sample.com/schema/sg
            http://code.sample.com/schema/sg/sg.xsd">    <sg:property-placeholder location="classpath*:conf/sample.properties"/>    <sg:application container-id="${sample.container.id}" container-port="${sample.container.default.port}"
                        register-http="${sample.governance.http.address}" register-tcp="${sample.governance.tcp.address}"
                        service-gateway="${sample.gateway.address}"/>    <sg:consume id="faceBundleImpBundle" providerId="${sample.provider.providerId}"
                    service="FaceBundleImpBundle" version="${sample.provider.version}" protocol="navi2json"
                interfaceType="com.sample.fbu.sample.agent.test.api.FaceBundleImpBundle"/>    <sg:consume id="faceBundleImpNoBundle" providerId="${sample.provider.providerId}"
                    service="FaceBundleImpNoBundle" version="${sample.provider.version}" protocol="navi2json"
                interfaceType="com.sample.fbu.sample.agent.test.api.FaceBundleImpNoBundle"/>    <sg:consume id="faceNoBundleImpBundle" providerId="${sample.provider.providerId}"
                    service="FaceNoBundleImpBundle" version="${sample.provider.version}" protocol="navi2json"
                interfaceType="com.sample.fbu.sample.agent.test.api.FaceNoBundleImpBundle"/>    <sg:consume id="faceNoBundleImpNoBundle" providerId="${sample.provider.providerId}"
                    service="FaceNoBundleImpNoBundle" version="${sample.provider.version}" protocol="navi2json"
                interfaceType="com.sample.fbu.sample.agent.test.api.FaceNoBundleImpNoBundle"/>    <sg:extend-property>        <sg:property key="sample.governance.gateway.ask.interval" value="30000"/>        <sg:property key="sample.service.auto-register" value="true"/>        <sg:property key="sample.service.requestlog" value="true"/>        <sg:property key="sample.governance.isolate.policy" value="QualityScore"/>        <sg:property key="sample.rpc.security.provider.key.1.(.+)" value="portal!Q@W#E$R"/>    </sg:extend-property>    <bean class="com.sample.ub.sample.container.support.bundle.ExtBundleContextPostProcessor">        <constructor-arg name="bundleName" value="consumerService"/>    </bean></beans>




4、自定义xml标签的schema定义

<?xml version="1.0" encoding="utf-8" standalone="no"?><xsd:schema    xmlns="http://code.sample.com/schema/sg">    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />    <xsd:import namespace="http://www.springframework.org/schema/beans" />    <xsd:import namespace="http://www.springframework.org/schema/tool" />    <xsd:annotation>        <xsd:documentation>            <![CDATA[ Namespace support for the service gateway.]]>        </xsd:documentation>    </xsd:annotation>    <xsd:simpleType name="protocolType">        <xsd:restriction base="xsd:NMTOKENS">            <xsd:enumeration value="navi2json" />            <xsd:enumeration value="navi2proto" />            <xsd:enumeration value="navi" />            <xsd:enumeration value="pbrpc" />            <xsd:enumeration value="jsonrpc" />            <xsd:enumeration value="msgpack" />        </xsd:restriction>    </xsd:simpleType>    <xsd:complexType name="abstractType">        <xsd:attribute name="service" type="xsd:string" use="required">            <xsd:annotation>                <xsd:documentation>                    <![CDATA[ The service name. ]]>                </xsd:documentation>            </xsd:annotation>        </xsd:attribute>        <xsd:attribute name="version" type="xsd:string" use="required">            <xsd:annotation>                <xsd:documentation>                    <![CDATA[ the service's version, should be an integer. ]]>                </xsd:documentation>            </xsd:annotation>        </xsd:attribute>        <xsd:attribute name="interfaceType" type="xsd:string" use="required">            <xsd:annotation>                <xsd:documentation>                    <![CDATA[ the interface type of that service. ]]>                </xsd:documentation>            </xsd:annotation>        </xsd:attribute>        <xsd:attribute name="protocol" type="protocolType" use="optional">            <xsd:annotation>                <xsd:documentation>                    <![CDATA[ the protocol type for rpc. ]]>                </xsd:documentation>            </xsd:annotation>        </xsd:attribute>    </xsd:complexType>    <xsd:complexType name="providerType">        <xsd:complexContent>            <xsd:extension base="abstractType">                <xsd:attribute name="routeStrategy" use="optional">                    <xsd:simpleType>                        <xsd:restriction base="xsd:NMTOKENS">                            <xsd:enumeration value="local" />                            <xsd:enumeration value="remote" />                            <xsd:enumeration value="switchover" />                        </xsd:restriction>                    </xsd:simpleType>                </xsd:attribute>                <xsd:attribute name="ref" type="xsd:string">                    <xsd:annotation>                        <xsd:documentation>                            <![CDATA[ the beanId of service which will be used in current project.
]]>                        </xsd:documentation>                    </xsd:annotation>                </xsd:attribute>            </xsd:extension>        </xsd:complexContent>    </xsd:complexType>    <xsd:complexType name="consumerType">        <xsd:complexContent>            <xsd:extension base="abstractType">                <xsd:attribute name="providerId" type="xsd:string" use="optional">                    <xsd:annotation>                        <xsd:documentation>                            <![CDATA[ The provider id. ]]>                        </xsd:documentation>                    </xsd:annotation>                </xsd:attribute>                <xsd:attribute name="selectStrategy" use="optional">                    <xsd:simpleType>                        <xsd:restriction base="xsd:NMTOKENS">                            <xsd:enumeration value="random" />                            <xsd:enumeration value="local_preference" />                            <xsd:enumeration value="remote_preference" />                            <xsd:enumeration value="high_available" />                        </xsd:restriction>                    </xsd:simpleType>                </xsd:attribute>                <xsd:attribute name="id" type="xsd:string">                    <xsd:annotation>                        <xsd:documentation>                            <![CDATA[ the beanId of service which will be used in current project.
]]>                        </xsd:documentation>                    </xsd:annotation>                </xsd:attribute>            </xsd:extension>        </xsd:complexContent>    </xsd:complexType>    <xsd:complexType name="applicationType">        <xsd:attribute name="container-id" type="xsd:string" use="required">            <xsd:annotation>                <xsd:documentation>                    <![CDATA[ The provider id. ]]>                </xsd:documentation>            </xsd:annotation>        </xsd:attribute>        <xsd:attribute name="container-port" type="xsd:string" use="required">            <xsd:annotation>                <xsd:documentation>                    <![CDATA[ The port of your service. ]]>                </xsd:documentation>            </xsd:annotation>        </xsd:attribute>        <xsd:attribute name="register-http" type="xsd:string" use="required">            <xsd:annotation>                <xsd:documentation>                    <![CDATA[ The http address of register-center. Separated by
comma ',', if you have multi addresses.]]>                </xsd:documentation>            </xsd:annotation>        </xsd:attribute>        <xsd:attribute name="register-tcp" type="xsd:string" use="required">            <xsd:annotation>                <xsd:documentation>                    <![CDATA[ The tcp address of register-center. Separated by
comma ',', if you have multi addresses.]]>                </xsd:documentation>            </xsd:annotation>        </xsd:attribute>        <xsd:attribute name="service-gateway" type="xsd:string" use="optional">            <xsd:annotation>                <xsd:documentation>                    <![CDATA[ The address of service gateway. Separated by
comma ',', if you have multi addresses.]]>                </xsd:documentation>            </xsd:annotation>        </xsd:attribute>    </xsd:complexType>    <xsd:complexType name="propertyType">        <xsd:attribute name="key" type="xsd:string" use="required">            <xsd:annotation>                <xsd:documentation>                    <![CDATA[ The name of property.]]>                </xsd:documentation>            </xsd:annotation>        </xsd:attribute>        <xsd:attribute name="value" type="xsd:string" use="required">            <xsd:annotation>                <xsd:documentation>                    <![CDATA[ The value of property.]]>                </xsd:documentation>            </xsd:annotation>        </xsd:attribute>    </xsd:complexType>    <xsd:complexType name="emptyType"></xsd:complexType>    <xsd:complexType name="extendPropertyType">        <xsd:complexContent>            <xsd:extension base="emptyType">                <xsd:choice>                    <xsd:element ref="property" minOccurs="1" maxOccurs="unbounded"></xsd:element>                </xsd:choice>            </xsd:extension>        </xsd:complexContent>    </xsd:complexType>    <xsd:complexType name="propertyLoading">        <xsd:attribute name="location" type="xsd:string">            <xsd:annotation>                <xsd:documentation>                    <![CDATA[
     The location of the properties file to resolve placeholders against, as a Spring
       resource location: a URL, a "classpath:" pseudo URL, or a relative file path.
  Multiple locations may be specified, separated by commas. If neither location nor
      properties-ref is specified, placeholders will be resolved against system properties.
                          ]]>                </xsd:documentation>            </xsd:annotation>        </xsd:attribute>        <xsd:attribute name="properties-ref" type="xsd:string">            <xsd:annotation>                <xsd:documentation source="java:java.util.Properties">                    <![CDATA[
    The bean name of a Properties object that will be used for property substitution.
      If neither location nor properties-ref is specified, placeholders will be resolved
     against system properties.
                             ]]>                </xsd:documentation>            </xsd:annotation>        </xsd:attribute>        <xsd:attribute name="file-encoding" type="xsd:string">            <xsd:annotation>                <xsd:documentation>                    <![CDATA[
        Specifies the encoding to use for parsing properties files. Default is none,
   using the java.util.Properties default encoding. Only applies to classic
       properties files, not to XML files.
                            ]]>                </xsd:documentation>            </xsd:annotation>        </xsd:attribute>        <xsd:attribute name="order" type="xsd:token">            <xsd:annotation>                <xsd:documentation>                    <![CDATA[
 Specifies the order for this placeholder configurer. If more than one is present
       in a context, the order can be important since the first one to be match a
     placeholder will win.
                          ]]>                </xsd:documentation>            </xsd:annotation>        </xsd:attribute>        <xsd:attribute name="ignore-resource-not-found" type="xsd:boolean" default="false">            <xsd:annotation>                <xsd:documentation>                    <![CDATA[
   Specifies if failure to find the property resource location should be ignored.
 Default is "false", meaning that if there is no file in the location specified
 an exception will be raised at runtime.
                                ]]>                </xsd:documentation>            </xsd:annotation>        </xsd:attribute>        <xsd:attribute name="ignore-unresolvable" type="xsd:boolean" default="false">            <xsd:annotation>                <xsd:documentation>                    <![CDATA[
 Specifies if failure to find the property value to replace a key should be ignored.
    Default is "false", meaning that this placeholder configurer will raise an exception
   if it cannot resolve a key. Set to "true" to allow the configurer to pass on the key
   to any others in the context that have not yet visited the key in question.
                            ]]>                </xsd:documentation>            </xsd:annotation>        </xsd:attribute>        <xsd:attribute name="local-override" type="xsd:boolean" default="false">            <xsd:annotation>                <xsd:documentation>                    <![CDATA[
      Specifies whether local properties override properties from files.
     Default is "false": Properties from files override local defaults.
                             ]]>                </xsd:documentation>            </xsd:annotation>        </xsd:attribute>    </xsd:complexType>    <xsd:complexType name="placeholderType">        <xsd:complexContent>            <xsd:extension base="propertyLoading">                <xsd:attribute name="system-properties-mode" default="ENVIRONMENT">                    <xsd:annotation>                        <xsd:documentation>                            <![CDATA[
  Controls how to resolve placeholders against system properties. As of Spring 3.1, this
 attribute value defaults to "ENVIRONMENT", indicating that resolution of placeholders
  against system properties is handled via PropertySourcesPlaceholderConfigurer and its
  delegation to the current Spring Environment object.

  For maximum backward compatibility, this attribute is preserved going forward with the
 3.1 version of the context schema, and any values other than the default "ENVIRONMENT"
 will cause a traditional PropertyPlaceholderConfigurer to be registered instead of the
 newer PropertySourcesPlaceholderConfigurer variant. In this case, the Spring Environment
       and its property sources are not interrogated when resolving placeholders. Users are
   encouraged to consider this attribute deprecated, and to take advantage of the
 Environment and PropertySource mechanisms. See ConfigurableEnvironment javadoc for examples.

  "ENVIRONMENT" indicates placeholders should be resolved against the current Environment and against any local properties;
      "NEVER" indicates placeholders should be resolved only against local properties and never against system properties;
   "FALLBACK" indicates placeholders should be resolved against any local properties and then against system properties;
  "OVERRIDE" indicates placeholders should be resolved first against system properties and then against any local properties;
                                                    ]]>                        </xsd:documentation>                    </xsd:annotation>                    <xsd:simpleType>                        <xsd:restriction base="xsd:string">                            <xsd:enumeration value="ENVIRONMENT" />                            <xsd:enumeration value="NEVER" />                            <xsd:enumeration value="FALLBACK" />                            <xsd:enumeration value="OVERRIDE" />                        </xsd:restriction>                    </xsd:simpleType>                </xsd:attribute>                <xsd:attribute name="value-separator" default=":">                    <xsd:annotation>                        <xsd:documentation>                            <![CDATA[
  The separating character between the placeholder variable and the associated
   default value: by default, a ':' symbol.
                               ]]>                        </xsd:documentation>                    </xsd:annotation>                </xsd:attribute>                <xsd:attribute name="null-value">                    <xsd:annotation>                        <xsd:documentation>                            <![CDATA[
     A value that should be treated as 'null' when resolved as a placeholder value:
 e.g. "" (empty String) or "null". By default, no such null value is defined.
                           ]]>                        </xsd:documentation>                    </xsd:annotation>                </xsd:attribute>            </xsd:extension>        </xsd:complexContent>    </xsd:complexType>    <xsd:element name="consume" type="consumerType">        <xsd:annotation>            <xsd:documentation>                <![CDATA[ The config for service provided by others.]]>            </xsd:documentation>        </xsd:annotation>    </xsd:element>    <xsd:element name="provide" type="providerType">        <xsd:annotation>            <xsd:documentation>                <![CDATA[ The config for service provider by yourself. ]]>            </xsd:documentation>        </xsd:annotation>    </xsd:element>    <xsd:element name="application" type="applicationType">        <xsd:annotation>            <xsd:documentation>                <![CDATA[ Global application config for yourself. ]]>            </xsd:documentation>        </xsd:annotation>    </xsd:element>    <xsd:element name="property" type="propertyType">        <xsd:annotation>            <xsd:documentation>                <![CDATA[ One property config. ]]>            </xsd:documentation>        </xsd:annotation>    </xsd:element>    <xsd:element name="extend-property" type="extendPropertyType">        <xsd:annotation>            <xsd:documentation>                <![CDATA[ Extended property set. ]]>            </xsd:documentation>        </xsd:annotation>    </xsd:element>    <xsd:element name="property-placeholder" type="placeholderType">        <xsd:annotation>            <xsd:documentation>                <![CDATA[ extend of spring property-placeholder.]]>            </xsd:documentation>        </xsd:annotation>    </xsd:element></xsd:schema>