• dubbo和springcloud问题解决——interface not allow null


    环境

    dubbo版本: 2.7.3

    springCloud版本: 2.2.0

    复现步骤

    当使用@Service注解注入dubbo provider到Spring容器中时,在dubbo provider的bean对象里依赖SpringCloud的bean时,触发报错,应用报错无法启动!

    dubbo provider bean

    @Service(registry = "dubbo-registry", interfaceClass = DubboProvideFacade.class)
    public class DubboProviderServiceImpl implements DubboProvideFacade {
      @Resource
    	private FeignClient feignClient;
      ······
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    SpringCloud Client

    @FeignClient(name = "feignClient", url = "${feign.client.config.url}", configuration = FeignClientInterceptor.class)
    public interface FeignClient {
      	······
    }
    
    • 1
    • 2
    • 3
    • 4

    报错

    报错图片

    Caused by: java.lang.IllegalStateException:  interface not allow null!
    	at org.apache.dubbo.config.ServiceConfig.checkAndUpdateSubConfigs(ServiceConfig.java:297)
    	at org.apache.dubbo.config.ServiceConfig.export(ServiceConfig.java:358)
    	at org.apache.dubbo.config.spring.ServiceBean.export(ServiceBean.java:327)
    	at org.apache.dubbo.config.spring.ServiceBean.onApplicationEvent(ServiceBean.java:105)
    	at org.apache.dubbo.config.spring.ServiceBean.onApplicationEvent(ServiceBean.java:51)
    	at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
    	at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
    	at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
    	at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:402)
    	at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:408)
    	at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:359)
    	at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:896)
    	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:552)
    	at org.springframework.cloud.context.named.NamedContextFactory.createContext(NamedContextFactory.java:136)
    	at org.springframework.cloud.context.named.NamedContextFactory.getContext(NamedContextFactory.java:101)
    	at org.springframework.cloud.context.named.NamedContextFactory.getInstance(NamedContextFactory.java:145)
    	at org.springframework.cloud.openfeign.FeignClientFactoryBean.get(FeignClientFactoryBean.java:224)
    	at org.springframework.cloud.openfeign.FeignClientFactoryBean.feign(FeignClientFactoryBean.java:85)
    	at org.springframework.cloud.openfeign.FeignClientFactoryBean.getTarget(FeignClientFactoryBean.java:261)
    	at org.springframework.cloud.openfeign.FeignClientFactoryBean.getObject(FeignClientFactoryBean.java:251)
    	at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:171)
    	... 142 common frames omitted
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    原因

    这个错误是由 Spring Cloud Feign 设计引起的,每个@FeignClient都会生成一个带有新子 Spring 的 Feign 代理,该子 SpringApplicationContext可能会在其 parent 之前刷新ApplicationContext。如果有注解@Service的 Dubbo 服务 bean 被子上下文扫描到,这个 DubboServiceBean也会被初始化,并且不能保证其依赖的 Spring bean 在那个时候已经准备好

    解决方式

    方式一(已验证)

    FeignClient使用ApplicationContextAware进行获取

    首先写一个SpringBean获取工具类

    @Component
    public class SpringBeanUtil implements ApplicationContextAware {
        private static ApplicationContext appContext;
    
        private static boolean hasBean(String name){
            return appContext.containsBean(name);
        }
    
        public static Object getBeanByName(String name) throws BeansException {
            return appContext.getBean(name);
        }
    
        public static Object getBeanByType(Class requiredType) throws BeansException {
            return appContext.getBean(requiredType);
        }
    
        public static Object getBeanIfPresent(String name){
            if(hasBean(name)){
                return getBeanByName(name);
            }
            return null;
        }
    
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            setAppContext(applicationContext);
        }
    
        private static synchronized void setAppContext(ApplicationContext appContext) {
            SpringBeanUtil.appContext = appContext;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    通过Util获取FeignClient而不是Spring注入的方式

    FeignClient client = SpringContextUtils.getBean(FeignClient.class)
    
    • 1

    方式二

    升级dubbo版本至2.7.9

    据说在2.7.9解决了改问题

    方式三

    一个不完美的解决方法是,让FeignClient以懒注入的方式进行注入

    @Service(registry = "dubbo-registry", interfaceClass = DubboProvideFacade.class)
    public class DubboProviderServiceImpl implements DubboProvideFacade {
      @Resource
      @Lazy
    	private FeignClient feignClient;
      ······
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
  • 相关阅读:
    APS车间排产软件实现企业生产数据可视化
    小技巧 | 渐变消失遮罩的多种实现方式
    码云gitee+宝塔webhook实现同步代码
    JAVA大学生过程培养信息系统计算机毕业设计Mybatis+系统+数据库+调试部署
    【Python】OpenCV-实时眼睛疲劳检测与提醒
    机器学习——聚类分析
    约瑟夫环问题——《算法》1.1.37的解法
    UNPV2 学习:Posix Message Queues
    Dynamics 365 Marketing自定义渠道的步骤
    如何适配国产数据库海量数据库
  • 原文地址:https://blog.csdn.net/m0_67392409/article/details/126328070