• dubbo 消费者重复订阅 @Reference注入不进Controller


    问题

    环境配置

    spring根application-context.xml、spring mvc的servlet-applicationcontext.xml引入了同一份dubbo.xml

    描述

    应用A启动后,dubbo-admin中有两个一模一样的消费者订阅。连接的zookeeper是本地的,而且只有应用A是消费者,没有其他应用订阅,所以推测是消费者订阅了两次。dubbo.xml中既有生产者也有消费者,在dubbo service构造方法中添加log,发现,构造方法执行了两次。

    初步解决

    check一遍配置文件发现,spring根配置文件、mvc配置文件都引入dubbo.xml,所以,在根上下文和mvc上下文各创建一份消费者。既然引入重复,那么将spring mvc中引用的dubbo.xml去掉,就解决了重复订阅问题。

    @Reference注入不进Controller

    但带来了新问题,@Reference注入不进Controller,这是为什么?我们知道自动注入的原理是BeanPostProcessor,跟踪源码,在DubboNamespaceHandler中注册的AnnotationBean就是BeanPostProcessor。

    在这里插入图片描述


    com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler#init

    public void init() {
            registerBeanDefinitionParser("annotation", new DubboBeanDefinitionParser(AnnotationBean.class, true));
        }
    
    • 1
    • 2
    • 3

    com.alibaba.dubbo.config.spring.AnnotationBean#postProcessBeforeInitialization

    public Object postProcessBeforeInitialization(Object bean, String beanName){
    Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                try {
                    if (! field.isAccessible()) {
                        field.setAccessible(true);
                    }
                    Reference reference = field.getAnnotation(Reference.class);
                	if (reference != null) {
                		//在这里获取@Reference值
    	                Object value = refer(reference, field.getType());
    	                if (value != null) {
    	                	field.set(bean, value);
    	                }
                	}
                } catch (Exception e) {
                    // modified by lishen
                    throw new BeanInitializationException("Failed to init remote service reference at filed " + field.getName() + " in class " + bean.getClass().getName(), e);
    //            	logger.error("Failed to init remote service reference at filed " + field.getName() + " in class " + bean.getClass().getName() + ", cause: " + e.getMessage(), e);
                }
            }
            return bean;
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    @Reference(com.alibaba.dubbo.config.annotation.Reference)就是AnnotationBean注入的。
    因为mvc不再扫描dubbo配置文件,所以也就没有AnnotationBean,那么自然不会注入@Reference。所以解决方案有两个,第一,去根上下文找dubbo service bean;第二,引入AnnotationBean。

    解决

    解决方案1

    • mvc不再引入dubbo.xml,根配置文件引入dubbo.xml
    • Controller中用@AutoWired引入dubbo servervice

    解决方案2

    • mvc引入只含有dubbo namespace的xml(没有dubbo bean),根配置文件引入dubbo.xml
    • Controller中用@Reference引入dubbo servervice

    知识拓展

    根上下文 vs MVC上下文
    根据spring doc得知,spring有根上下文和mvc上下文,根上下文是mvc上下文的父上下文,满足有父上下文&&当前上下文不含有此bean定义时,从父上下文获取,上边的解决方案1就是利用的这点。
    这里写图片描述

  • 相关阅读:
    Java线程与锁-2
    Android内存回收机制、GC算法及内存问题分析解决
    Electron之单例+多窗口
    Windows下搜索文件内容的关键字用什么命令
    深度入门 Android 车机核心 CarService 的构成和链路
    04-Jenkins构建Maven项目
    35-Git
    [2023.09.13]: Rust Lang,避不开的所有权问题
    C语言趣味代码(一)
    Spring 面试 63 问!
  • 原文地址:https://blog.csdn.net/m0_67402013/article/details/126327789