【dubbo源码分析】7.dubbo服务端-dubbo-provider加载过程

11 篇文章 0 订阅

本文使用的是dubbo-2.5.8版,

注册中心是zk(使用不同端口构建第一个伪集群)

配置文件: debbo-demo-provider.xml
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xmlns="http://www.springframework.org/schema/beans"
       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">

    <!-- 提供方应用信息,用于计算依赖关系 -->
    <dubbo:application name="demo-provider"/>

    <!-- 使用multicast广播注册中心暴露服务地址 -->
    <!-- <dubbo:registry address="multicast://224.5.6.7:1234"/> -->
    <dubbo:registry protocol="zookeeper" address="10.0.28.54:2181;10.0.28.54:2182;10.0.28.54:2183"/>

    <!-- 用dubbo协议在20880端口暴露服务 -->
    <dubbo:protocol name="dubbo" port="20880"/>

    <!-- 和本地bean一样实现服务 -->
    <bean id="demoService" class="com.alibaba.dubbo.demo.provider.DemoServiceImpl"/>

    <!-- 声明需要暴露的服务接口 -->
    <dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService"/>

</beans>
服务容器启动:在dubbo-demo-provider项目中
public class Provider {

    public static void main(String[] args) throws Exception {
        //Prevent to get IPV6 address,this way only work in debug mode
        //But you can pass use -Djava.net.preferIPv4Stack=true,then it work well whether in debug mode or not
        System.setProperty("java.net.preferIPv4Stack", "true");
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo-demo-provider.xml"});
        context.start();
        System.in.read(); // press any key to exit
    }
}
Main启动spring容器加载 META-INF/spring/dubbo-demo-provider.xml 进行初始化,设置上下文;
这个过程spring会读取classptsh:META-INF下的 spring.handler文件,加载解析 xsd文件的Handler:【DubboNamespaceHandler】解析xsd定义的节点;
我们看到DubboNamespaceHandler对service节点的解析为 registerBeanDefinitionParser("service", new DubboBeanDefinitionParser(ServiceBean.class, true));

    下面来看看ServiceBean.java

public class ServiceBean<T> extends ServiceConfig<T> implements InitializingBean, DisposableBean, ApplicationContextAware, ApplicationListener<ContextRefreshedEvent>, BeanNameAware {
public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
        SpringExtensionFactory.addApplicationContext(applicationContext);
        if (applicationContext != null) {
            SPRING_CONTEXT = applicationContext;
            try {
                Method method = applicationContext.getClass().getMethod("addApplicationListener", new Class<?>[]{ApplicationListener.class}); // 兼容Spring2.0.1
                method.invoke(applicationContext, new Object[]{this});
                supportedApplicationListener = true;
            } catch (Throwable t) {
                if (applicationContext instanceof AbstractApplicationContext) {
                    try {
                        Method method = AbstractApplicationContext.class.getDeclaredMethod("addListener", new Class<?>[]{ApplicationListener.class}); // 兼容Spring2.0.1
                        if (!method.isAccessible()) {
                            method.setAccessible(true);
                        }
                        method.invoke(applicationContext, new Object[]{this});
                        supportedApplicationListener = true;
                    } catch (Throwable t2) {
                    }
                }
            }
        }
    }

    public void onApplicationEvent(ContextRefreshedEvent event) {
        if (isDelay() && !isExported() && !isUnexported()) {
            if (logger.isInfoEnabled()) {
                logger.info("The service ready on spring started. service: " + getInterface());
            }
            export();
        }
    }

    private boolean isDelay() {
        Integer delay = getDelay();  //==null
        ProviderConfig provider = getProvider();
        if (delay == null && provider != null) {
            delay = provider.getDelay();
        }
        return supportedApplicationListener && (delay == null || delay == -1);   //return ture;
    }
}
ServiceBean分别实现了 ApplicationContextAware接口,因此在启动的时候spring会自动将上下文applicationContext 通过 setApplicationContext 方法将spring上下文注入到 ServiceBean中,以备后续使用;
InitializingBean.afterPropertiesSet() 方法会使用到 applicationContext afterProperties最后会判断
if (!isDelay()) {
export();
}
由处理逻辑可知,isDelay 返回ture,所以export()方法不是在 afterProperties方法处执行;
又 实现 ApplicationListener 接口,负责在初始化的时候会触发事件,并通过调用重载方法 onApplicationEvent 来进行初始化。因此,ServiceBean的export() 方法是在触发事件的时候才真正执行。

     export()方法经过 doExport() , doExportUrls() ,doExportUrlsFor1Protocol ()后才真正的开始执行服务端相关逻辑。

        其中 doExport()主要负责参数相关的校验;

         doExportUrls()首先会

        1.获取注册中心地址列表

List<URL> registryURLs = loadRegistries(true);
        2. 根据注册中心地址列表和 协议【 protocols 】 对服务进行暴露。
由配置文件可知 protocols =[dubbo] 【 <dubbo:protocol name="dubbo" port="20880"/>
接下来根据registryUrls和protocol对服务进行注册。【详细解答请查看 DubboProvider服务端暴露过程详解







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值