我是靠谱客的博主 复杂小懒猪,最近开发中收集的这篇文章主要介绍dubbo 加载Bean和远程调用分析(1),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

这里只讲解dubbo注册的bean

1. dubbo consumer 加载bean  

dubbo-2.5.3.jar!/spring.handlers

http://code.alibabatech.com/schema/dubbo=com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler

DubboNamespaceHandler 是dubbo命名空间自定义配置文件的解析处理器

public class DubboNamespaceHandler extends NamespaceHandlerSupport {

	static {
		Version.checkDuplicate(DubboNamespaceHandler.class);
	}

	public void init() {
	    registerBeanDefinitionParser("application", new DubboBeanDefinitionParser(ApplicationConfig.class, true));
        registerBeanDefinitionParser("module", new DubboBeanDefinitionParser(ModuleConfig.class, true));
        registerBeanDefinitionParser("registry", new DubboBeanDefinitionParser(RegistryConfig.class, true));
        registerBeanDefinitionParser("monitor", new DubboBeanDefinitionParser(MonitorConfig.class, true));
        registerBeanDefinitionParser("provider", new DubboBeanDefinitionParser(ProviderConfig.class, true));
        registerBeanDefinitionParser("consumer", new DubboBeanDefinitionParser(ConsumerConfig.class, true));
        registerBeanDefinitionParser("protocol", new DubboBeanDefinitionParser(ProtocolConfig.class, true));
        registerBeanDefinitionParser("service", new DubboBeanDefinitionParser(ServiceBean.class, true));
        registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false));
        registerBeanDefinitionParser("annotation", new DubboBeanDefinitionParser(AnnotationBean.class, true));
    }

}


spring会根据xml的命名空间调用响应的Parser进行处理,进入 DubboBeanDefinitionParser的解析parse

private static BeanDefinition parse(Element element, ParserContext parserContext, Class<?> beanClass, boolean required) {
        RootBeanDefinition beanDefinition = new RootBeanDefinition();
        beanDefinition.setBeanClass(beanClass);
        beanDefinition.setLazyInit(false);
        String id = element.getAttribute("id");
        省略.... 
        if (id != null && id.length() > 0) {
            if (parserContext.getRegistry().containsBeanDefinition(id))  {
        		throw new IllegalStateException("Duplicate spring bean id " + id);
        	}
            parserContext.getRegistry().registerBeanDefinition(id, beanDefinition);//这里调用了bean的注册
            beanDefinition.getPropertyValues().addPropertyValue("id", id);
        }
        省略.... 
}

这一步注意,虽然注册的bean id(如 demoService) 是与privider端的service的id相同的,但是这里beanDefinition的beanClass却不是自己定义的某个接口了。

在spring解析配置beans时先生成bean的定义,然后getBean时,是通过className获取Class,然后设置bd.setBeanClass(class)

org.springframework.beans.factory.support.AbstractBeanFactory

	private Class<?> doResolveBeanClass(RootBeanDefinition mbd, Class<?>... typesToMatch) throws ClassNotFoundException {
		if (!ObjectUtils.isEmpty(typesToMatch)) {
			ClassLoader tempClassLoader = getTempClassLoader();
			if (tempClassLoader != null) {
				if (tempClassLoader instanceof DecoratingClassLoader) {
					DecoratingClassLoader dcl = (DecoratingClassLoader) tempClassLoader;
					for (Class<?> typeToMatch : typesToMatch) {
						dcl.excludeClass(typeToMatch.getName());
					}
				}
				String className = mbd.getBeanClassName();
				return (className != null ? ClassUtils.forName(className, tempClassLoader) : null);
			}
		}
		return mbd.resolveBeanClass(getBeanClassLoader());
	}

在执行 
registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false));

时已经将 DubboBeanDefinitionParser.beanClass  = ReferenceBean.class

故在解析时实际是如下形式

RootBeanDefinition beanDefinition = new RootBeanDefinition();
        beanDefinition.setBeanClass(beanClass); //ReferenceBean.class
        beanDefinition.setLazyInit(false);

即将id=demoService 与 类 
ReferenceBean

绑定,放入map, 即使用的是FactoryBean来创建bean

当spring使用getBean(‘demoService“) 会调用工厂bean的getObject  :  ReferenceBean.getObject

在看看ReferenceBean.getObject

public Object getObject() throws Exception {
        return get();
    }
 public synchronized T get() {
        if (destroyed){
            throw new IllegalStateException("Already destroyed!");
        }
    	if (ref == null) {
    		init();
    	}
    	return ref;
    }

  private void init() {
	    if (initialized) {
	        return;
	    }
	    initialized = true;
    	省略....
        ref = createProxy(map);//在这里使用了动态代理生成对象
    }

ref = createProxy(map);//在这里使用了动态代理生成了代理对象(这里也可以成为远程代理,因为在这个代理中进行了远程调用),ref 即getBean返回的对象,这样在action调用demoService是就会使用代理处理器com.alibaba.dubbo.rpc.proxy.InvokerInvocationHandler
public class InvokerInvocationHandler implements InvocationHandler {

    private final Invoker<?> invoker;
    
    public InvokerInvocationHandler(Invoker<?> handler){
        this.invoker = handler;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        String methodName = method.getName();
        Class<?>[] parameterTypes = method.getParameterTypes();
        if (method.getDeclaringClass() == Object.class) {
            return method.invoke(invoker, args);
        }
        if ("toString".equals(methodName) && parameterTypes.length == 0) {
            return invoker.toString();
        }
        if ("hashCode".equals(methodName) && parameterTypes.length == 0) {
            return invoker.hashCode();
        }
        if ("equals".equals(methodName) && parameterTypes.length == 1) {
            return invoker.equals(args[0]);
        }
        return invoker.invoke(new RpcInvocation(method, args)).recreate();
    }

}

看最后一句  invoker.invoke(new RpcInvocation(method, args)).recreate(); 这里就开始进入调用远程的服务



最后

以上就是复杂小懒猪为你收集整理的dubbo 加载Bean和远程调用分析(1)的全部内容,希望文章能够帮你解决dubbo 加载Bean和远程调用分析(1)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(39)

评论列表共有 0 条评论

立即
投稿
返回
顶部