千家信息网

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

发表于:2025-02-01 作者:千家信息网编辑
千家信息网最后更新 2025年02月01日,这篇文章主要介绍"怎么用Dubbo与Spring整合解析配置文件",在日常操作中,相信很多人在怎么用Dubbo与Spring整合解析配置文件问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法
千家信息网最后更新 2025年02月01日怎么用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整合解析配置文件"的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注网站,小编会继续努力为大家带来更多实用的文章!

文件 配置 容器 属性 过程 分析 整合 学习 生成 代码 就是 提供者 方法 消费者 反射 延迟 服务 消费 更多 源码 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 综合软件开发调试 即学即用网络技术有限公司 邮件网关服务器入什么费用 网络安全教育主题班会课 银行网络安全审计学习体会 软件开发事业部是干嘛的 罗湖区网络技术进出口联系方式 光遇显示服务器内部出问题 网络安全专题1 甘南州网络安全周 前端登录页面连接后端数据库 如何设置两个拨号服务器 网络安全排查报告范本 软件开发人员费用预算表 美国软件开发例子 网络安全管理制度体系评审表 净网2018网络安全行动 更改数据库表列的长度 我的世界服务器招人网易 软件开发都可以升什么条件 华为手机连接到服务器 惠州思科网络技术学院 虚拟机服务器共享文件 幼儿园网络安全等级保护制度 我的世界脏小豆网易服务器 英拓网络技术有限公司游戏 linux服务器安全报告 游卡网络技术有限公司占地 影院投影机连不上服务器 网络安全的目标是哪五个
0