xml发生错误_dubbo-从xml文件加载api接口的过程

dubbo和spring boot集成后,可以通过配置spring/dubbo-consumer.xml来配置需要调用的生产者。那么配置好后,到spring boot启动加载dubbo api的具体过程是什么样的呢?为了探索这个过程,分析了下源码。

首先,从dubbo-demo源码模块,找到了dubbo-demo-xml-consumer目录下的demo,从main函数开始debug整个加载过程。main函数如下:

public class Application {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/dubbo-consumer.xml");
        context.start();
        DemoService demoService = context.getBean("demoService", DemoService.class);
        String hello = demoService.sayHello("world");
        System.out.println("result: " + hello);
    }
}

dubbo-consumer的xml文件如下:

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://dubbo.apache.org/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-4.3.xsd
       http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
    <dubbo:application name="demo-consumer"/>
    <dubbo:registry address="zookeeper://127.0.0.1:2181"/>
    <dubbo:reference id="demoService" check="false" interface="org.apache.dubbo.demo.DemoService"/>

</beans>

这里主要关注xsd文件的配置,引用的xsd文件包括spring的spring-beans-4.3.xsd文件和dubbo.xsd,这两个xsd文件分别定义了xml文件的解析规则。 例如看dubbo: reference,在xsd文件中可以看到reference对应的配置,对应ReferenceConfig类。

<xsd:element name="reference" type="referenceType">
        <xsd:annotation>
            <xsd:documentation><![CDATA[ Reference service config ]]></xsd:documentation>
            <xsd:appinfo>
                <tool:annotation>
                    <tool:exports type="org.apache.dubbo.config.ReferenceConfig"/>
                </tool:annotation>
            </xsd:appinfo>
        </xsd:annotation>
    </xsd:element>

总体的逻辑是context.start();的时候会根据xsd规则,实例化xml文件中配置的对象,例如将refer的配置,加载到ReferenceConfig的实例化对象中。context.start()完成后执行完成后,这些配置类都已经加载完成。

context.getBean("demoService", DemoService.class);发生了哪些事情?

这里故意配置错误的ZK让抛出异常,方便跟踪异常栈。

130590a7a761112a6ad582dfbd967643.png

spring 最后会根据beanName和bean对应的factory构建bean。简略的代码如下:

object = doGetObjectFromFactoryBean(factory, beanName);
object = factory.getObject();

0813de43eaa33d3a335fa378c0d39d46.png

那么 object = factory.getObject();中factory是具体哪个类呢,观察dubbo抛出的异常栈。

发现是ReferenceBean,ReferenceBean也是一个factory,继承了ReferenceConfig和Factorybean。

public class ReferenceBean<T> extends ReferenceConfig<T> implements FactoryBean, ApplicationContextAware, InitializingBean, DisposableBean

ReferenceConfig中get方法会调用,init方法初始化,初始化包括ZK连接,这里抛出异常也是初始化过程中抛出的。

ReferenceBean是如何关联上demoService的创建过程的?

doGetbean的过程会调用这个方法,改方法从单例对象池中获取ReferenceBean。

Object sharedInstance = getSingleton(beanName);

单例对象池的列表如下:key是serviceName,所以ReferenceBean是context启动的时候就初始化到单例池中。

39b4c3763bd6c905b09b6b9619a7cdfa.png

sharedInstance就是一个RefenceBean实例,每一个refer配置都会在单例池中创建一个RefenceBean对象。

bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
从缓存中取。
if (mbd == null) {
			object = getCachedObjectForFactoryBean(beanName);
		}
if (object == null) {
			// Return bean instance from factory.
			FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
			// Caches object obtained from FactoryBean if it is a singleton.
			if (mbd == null && containsBeanDefinition(beanName)) {
				mbd = getMergedLocalBeanDefinition(beanName);
			}
			boolean synthetic = (mbd != null && mbd.isSynthetic());
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
object = doGetObjectFromFactoryBean(factory, beanName);
object = factory.getObject();

ReferenceConfig,获取对象过程。

public synchronized T get() {
        if (destroyed) {
            throw new IllegalStateException("The invoker of ReferenceConfig(" + url + ") has already destroyed!");
        }
        if (ref == null) {
            checkAndUpdateSubConfigs();
            init();
        }
        return ref;
    }

init方法过程:

初始化参数,创建代理,构建serviceKey,初始化消费者model。

map.put(REGISTER_IP_KEY, hostToRegistry);

        ref = createProxy(map);

        String serviceKey = URL.buildKey(interfaceName, group, version);
        ApplicationModel.initConsumerModel(serviceKey, buildConsumerModel(serviceKey, attributes));

createProxy方法会检测注册状态,调用AbstractInterfaceConfig.checkRegistry();方法。ReferenceConfig继承了AbstractReferenceConfig。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值