解析服务

Spring提供了可扩展Schema的支持,完成一个自定义配置一般需要以下步骤:

  • 设计配置属性和JavaBean
  • 编写XSD文件
  • 编写NamespaceHandler和BeanDefinitionParser完成解析工作。
  • 编写spring.handlers和spring.schemas串联所有部件。
  • 在Bean文件中应用

1.设计配置属性和JavaBean

以Dubbo的ServiceBean为例,这里定义了dubbo每个服务的信息。ServiceBean类的关系图如下图:

dubbo注册到nacos上面的ip_spring

2.编写XSD文件

以dubbo:service为例:

<xsd:element name="service" type="serviceType"> 
        <xsd:annotation> 
            <xsd:documentation><![CDATA[ Export service config ]]></xsd:documentation> 
        </xsd:annotation> 
</xsd:element>

 

serviceType类型的定义如下:

 

<xsd:complexType name="serviceType"> 
        <xsd:complexContent> 
            <xsd:extension base="abstractServiceType"> 
                <xsd:choice minOccurs="0" maxOccurs="unbounded"> 
                    <xsd:element ref="method" minOccurs="0" maxOccurs="unbounded" /> 
                    <xsd:element ref="parameter" minOccurs="0" maxOccurs="unbounded" /> 
                    <xsd:element ref="beans:property" minOccurs="0" maxOccurs="unbounded" /> 
                </xsd:choice> 
                <xsd:attribute name="interface" type="xsd:token" use="required"> 
                    <xsd:annotation> 
                        <xsd:documentation><![CDATA[ Defines the interface to advertise for this service in the service registry. ]]></xsd:documentation> 
                        <xsd:appinfo> 
                            <tool:annotation> 
                                <tool:expected-type type="java.lang.Class"/> 
                            </tool:annotation> 
                        </xsd:appinfo> 
                    </xsd:annotation> 
                </xsd:attribute> 
                <xsd:attribute name="ref" type="xsd:string" use="optional"> 
                    <xsd:annotation> 
                        <xsd:documentation><![CDATA[ The service implementation instance bean id. ]]></xsd:documentation>
                    </xsd:annotation> 
                </xsd:attribute> 
                <xsd:attribute name="class" type="xsd:string" use="optional"> 
                    <xsd:annotation> 
                        <xsd:documentation><![CDATA[ The service implementation class name. ]]></xsd:documentation> 
                    </xsd:annotation> 
                </xsd:attribute> 
                <xsd:attribute name="path" type="xsd:string" use="optional"> 
                    <xsd:annotation> 
                        <xsd:documentation><![CDATA[ The service path. ]]></xsd:documentation> 
                    </xsd:annotation> 
                </xsd:attribute> 
                <xsd:attribute name="provider" type="xsd:string" use="optional"> 
                    <xsd:annotation> 
                        <xsd:documentation><![CDATA[ Deprecated. Replace to protocol. ]]></xsd:documentation> 
                    </xsd:annotation> 
                </xsd:attribute> 
                <xsd:attribute name="generic" type="xsd:string" use="optional"> 
                    <xsd:annotation> 
                        <xsd:documentation><![CDATA[ Generic service. ]]></xsd:documentation> 
                    </xsd:annotation> 
                </xsd:attribute> 
                <xsd:anyAttribute namespace="##other" processContents="lax" /> 
            </xsd:extension> 
        </xsd:complexContent> 
    </xsd:complexType>

 

比如其中的<xsd:attribute name="ref" type="xsd:string" use="optional" >对应的string类型的配置项ref。

 

3.编写NamespaceHandler和BeanDefinitionParser完成解析工作

具体说来NamespaeHandler会根据schema和节点名找到某个BeanDefinitionParser,然后由BeanDefinitionParser完成具体的解析工作。因此需要分别完成NamespaceHandler和BeanDefinitionParser的实现类,Spring提供了默认实现类NamespaceHandlerSupport和AbstractSingleBeanDefintionParser,简单的方式就去

继承这两个类。

 

4.编写spring.handlers和spring.schemas串联起所有部件

spring.handlers文件的内容如下:

http\://code.alibabatech.com/schema/dubbo=com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler

以上表示当使用名为“http://code.alibabatech.com/schema/dubbo”的schema引用时,会通过DubboNamespaceHandler来完成解析过程。

spring.schemas文件的内容如下:

http\://code.alibabatech.com/schema/dubbo/dubbo.xsd=META-INF/dubbo.xsd

以上表示载入xsd文件的位置。

 

这两个文件放在META-INF下,spring会默认去载入它们。

 

5.在Bean文件中应用

<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
    http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"> 
    
    <bean id="demoService" class="com.alibaba.dubbo.demo.provider.DemoServiceImpl" /> 
    <dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService" /> 
    
</beans>

其中:

  • xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"是用来指定自定义schema
  • xsi:schemaLocation用来指定xsd文件
  • <dubbo:service..>是一个具体的自定义配置使用实例

配置文件的解析过程

  • 基于META-INF/spring.handler配置,Spring在遇到dubbo名称空间时,会回调DubboNamespaceHandler。
  • 所有dubbo的标签,都统一用DubboBeanDefinitionParser进行解析,基于一对一属性映射,将XML标签解析为Bean对象。

Spring Bean的生命周期:

dubbo注册到nacos上面的ip_xml_02

 

Bean的完整生命周期经历了各种方式调用,这些方法可以划分为以下几类:

  • Bean自身的方法:这个包括Bean本身调用的方法和通过配置文件中<bean>的init-method和destroy-method指定的方法。
  • Bean级生命周期接口方法:这个包括BeanNameAware、 BeanFactoryAware、InitializingBean和DisposableBean这些接口的方法。
  • 容器级生命周期接口方法:这个包括了InstantiationAwareBeanPostProcessor和BeanPostProcessor这两个接口实现,一般称它们的实现类为“后处理器”。
  • 工厂后处理器接口方法:这个包括了AspectJWeavingEabler、ConfigurationClassPostProcessor、CustomAutowireConfigurer等等非常有用的工厂后处理器接口的方法。工厂后处理器也是容器级的,在应用上下文装配文件后立即调用。

 

以ServiceBean为例:

 

在afterPropertiesSet后,会调用到ServiceConfig.export()。生产者在ServiceConfig.export或者在ReferenceConfig.get初始化时,将Bean对象转换URL格式,所有Bean属性转成URL的参数。(学会查看调用堆栈)。

 

然后将URL传给Protocol扩展点,基于扩展点的Adaptive机制,根据URL的协议头,进行不同协议的服务暴露或引用。