怎么用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);
				}
			}
		}
	}
}

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

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();
		}
	}
}

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

// 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整合解析配置文件

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


文章题目:怎么用Dubbo与Spring整合解析配置文件
新闻来源:http://cdiso.cn/article/piejep.html

其他资讯