解析服务
Spring提供了可扩展Schema的支持,完成一个自定义配置一般需要以下步骤:
- 设计配置属性和JavaBean
- 编写XSD文件
- 编写NamespaceHandler和BeanDefinitionParser完成解析工作。
- 编写spring.handlers和spring.schemas串联所有部件。
- 在Bean文件中应用
1.设计配置属性和JavaBean
以Dubbo的ServiceBean为例,这里定义了dubbo每个服务的信息。ServiceBean类的关系图如下图:
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的生命周期:
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的协议头,进行不同协议的服务暴露或引用。