千家信息网

怎么用Dubbo与Spring整合解析配置文件

发表于:2025-12-02 作者:千家信息网编辑
千家信息网最后更新 2025年12月02日,这篇文章主要介绍"怎么用Dubbo与Spring整合解析配置文件",在日常操作中,相信很多人在怎么用Dubbo与Spring整合解析配置文件问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法
千家信息网最后更新 2025年12月02日怎么用Dubbo与Spring整合解析配置文件

这篇文章主要介绍"怎么用Dubbo与Spring整合解析配置文件",在日常操作中,相信很多人在怎么用Dubbo与Spring整合解析配置文件问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"怎么用Dubbo与Spring整合解析配置文件"的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

1、Dubbo消费者调用服务提供者例子

本专栏分析的Dubbo源码是基于2.6.x版本

public class Consumer {    public static void main(String[] args) {        ClassPathXmlApplicationContext context =                             new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo-demo-consumer.xml"});        context.start();        DemoService demoService = (DemoService) context.getBean("demoService");        while (true) {            try {                Thread.sleep(1000);                String hello = demoService.sayHello("world");                System.out.println(hello);             } catch (Throwable throwable) {                throwable.printStackTrace();            }        }    }}
            
public class Provider {    public static void main(String[] args) throws Exception {        System.setProperty("java.net.preferIPv4Stack", "true");        ClassPathXmlApplicationContext context =                             new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo-demo-provider.xml"});        context.start();        System.in.read();     }}
                    

2、Spring解析dubbo配置文件

  先启动服务提供者,再启动消费者,发现控制台可以正常输出。下面分析一下Spring是如何解析dubbo的消费者和服务提供者的配置文件。Spring容器提供了IOC功能,可以替我们生成bean。通常,我们将bean的定义放在xml文件中,我们来分析一下Spring加载xml配置文件并生成bean过程。Spring提供的容器分为两种:BeanFactory和ApplicationContext。其中BeanFactory是懒加载,也就是延迟初始化,它在你调用getBean时才会初始化这个bean,而ApplicationContext是初始化容器时就会加载非延迟初始化的bean。先简单概况下Spring容器生成bean的过程,首先通过loadBeanDefinition过程将bean的信息封装成一个个BeanDefinition,然后再根据这些BeanDefinition创建bean。下面看Spring解析Dubbo的配置文件并生成bean的过程。

// 1、new ClassPathXmlApplicationContext时Spring容器初始化,此时会先调用loadBeanDefinition方法去加载解析xml配置文件context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo-demo-provider.xml"});
// 2、加载配置文件最终会走到这里protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {        if (delegate.isDefaultNamespace(root)) {                NodeList nl = root.getChildNodes();                // 3、这里其实已经通过dom4j将xml文件解析成了Document,将xml中的一项一项配置解析成了一个个Node去读取处理.                for (int i = 0; i < nl.getLength(); i++) {                        Node node = nl.item(i);                        if (node instanceof Element) {                                Element ele = (Element) node;                                // 4、判断是否是Spring默认可以处理的Node.这里看下面截图,由于dubbo:application,                                // 是dubbo中定义的,不属于Spring的命名空间管理                                if (delegate.isDefaultNamespace(ele)) {                                        parseDefaultElement(ele, delegate);                                }                                else {                                        delegate.parseCustomElement(ele);                                }                        }                }        }}

public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {        // http://dubbo.apache.org/schema/dubbo        String namespaceUri = getNamespaceURI(ele);        // DubboNameSpaceHandler        NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);        if (handler == null) {                return null;        }        return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));}
private static BeanDefinition parse(Element element, ParserContext parserContext,                                                                            Class beanClass, boolean required) {        RootBeanDefinition beanDefinition = new RootBeanDefinition();        // class com.alibaba.dubbo.config.ApplicationConfig        beanDefinition.setBeanClass(beanClass);        beanDefinition.setLazyInit(false);        // 解析id属性        String id = element.getAttribute("id");        if ((id == null || id.length() == 0) && required) {            String generatedBeanName = element.getAttribute("name");            if (generatedBeanName == null || generatedBeanName.length() == 0) {                if (ProtocolConfig.class.equals(beanClass)) {                    generatedBeanName = "dubbo";                } else {                    generatedBeanName = element.getAttribute("interface");                }            }            if (generatedBeanName == null || generatedBeanName.length() == 0) {                generatedBeanName = beanClass.getName();            }            id = generatedBeanName;            int counter = 2;            while (parserContext.getRegistry().containsBeanDefinition(id)) {                id = generatedBeanName + (counter++);            }        }        if (id != null && id.length() > 0) {            if (parserContext.getRegistry().containsBeanDefinition(id)) {                throw new IllegalStateException("Duplicate spring bean id " + id);            }            // 注册BeanDefinition            parserContext.getRegistry().registerBeanDefinition(id, beanDefinition);            // 将id属性放入beanDefinition中,后续getBean创建bean时就是根据这些属性来创建bean,            // 这里创建的bean是ApplicationConfig            beanDefinition.getPropertyValues().addPropertyValue("id", id);        }        // 删去一些代码,reference是解析得到的value值,可见这里将属性和属性值都放入了BeanDefinition        beanDefinition.getPropertyValues().addPropertyValue(property, reference);        return beanDefinition;}

到这里就解析完了,Spring将xml中的application节点解析成一个BeanDefinition,并注册到Registry中,Registry就是一个Map。下面分析Spring创建这个ApplicationConfig的过程。

3、Spring创建ApplicationConfig

context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo-demo-provider.xml"});
// Spring容器的初始化过程,new ClassPathXmlApplicationContext后会走到这里public void refresh() throws BeansException, IllegalStateException {        synchronized (this.startupShutdownMonitor) {                prepareRefresh();                // 这里面就会执行上面的分析过程,调用loadBeanDefinition解析BeanDefinition                ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();                prepareBeanFactory(beanFactory);                try {                        postProcessBeanFactory(beanFactory);                        invokeBeanFactoryPostProcessors(beanFactory);                        registerBeanPostProcessors(beanFactory);                        initMessageSource();                        initApplicationEventMulticaster();                        onRefresh();                        registerListeners();                        // Instantiate all remaining (non-lazy-init) singletons.可以看到Spring容器初始化                        // 的后面会初始化非延迟加载的bean,这里会走到下图的preInstantiasteSingletons方法                        finishBeanFactoryInitialization(beanFactory);                        finishRefresh();                }        }}

// Spring创建bean最终会走到这里protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd,                                                      final Object[] args) throws BeanCreationException {        BeanWrapper instanceWrapper = null;        if (mbd.isSingleton()) {                instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);        }        if (instanceWrapper == null) {                // 删除一些无用代码,这里会调用反射创建bean,创建完仅是一个空的bean,属性还没有赋值                instanceWrapper = createBeanInstance(beanName, mbd, args);        }        final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);        Object exposedObject = bean;        try {                // 属性赋值,最终也是调用反射进行赋值                populateBean(beanName, mbd, instanceWrapper);                if (exposedObject != null) {                        exposedObject = initializeBean(beanName, exposedObject, mbd);                }        }        return exposedObject;}
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {        // 这里的pvs就是之前解析配置文件得到BeanDefinition时,给BeanDefinition注入进去的        PropertyValues pvs = mbd.getPropertyValues();        // 删除一些代码,最终这里会调用反射赋值,跳来跳去有点复杂        applyPropertyValues(beanName, mbd, bw, pvs);}
protected void addSingleton(String beanName, Object singletonObject) {        // 最终创建完bean以后会将它保存起来(猜测,Spring容器初始化以后,非懒加载的bean已经以如下方式        // 保存到Spring容器中了,后续通过@Autowired注解)来获取时就是从这里面获取,只是分析,还没有看源码)        synchronized (this.singletonObjects) {                this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));                this.singletonFactories.remove(beanName);                this.earlySingletonObjects.remove(beanName);                this.registeredSingletons.add(beanName);        }}

到此,关于"怎么用Dubbo与Spring整合解析配置文件"的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注网站,小编会继续努力为大家带来更多实用的文章!

0