Loading... ## 环境 **dubbo版本:** 2.7.3 **springCloud版本:** 2.2.0 ## 复现步骤 当使用`@Service`注解注入`dubbo provider`到Spring容器中时,在`dubbo provider`的bean对象里依赖`SpringCloud`的bean时,触发报错,应用报错无法启动! ### dubbo provider bean ```java @Service(registry = "dubbo-registry", interfaceClass = DubboProvideFacade.class) public class DubboProviderServiceImpl implements DubboProvideFacade { @Resource private FeignClient feignClient; ······ } ``` ### SpringCloud Client ```java @FeignClient(name = "feignClient", url = "${feign.client.config.url}", configuration = FeignClientInterceptor.class) public interface FeignClient { ······ } ``` ## 报错 ![报错图片](https://image.juinjonn.com:8888/local/2023/01/13/63c11123e8c52.png) ```java Caused by: java.lang.IllegalStateException: <dubbo:service interface="" /> 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 ``` ## 原因 这个错误是由 Spring Cloud Feign 设计引起的,每个`@FeignClient`都会生成一个带有新子 Spring 的 Feign 代理,该子 Spring`ApplicationContext`可能会在其 parent 之前刷新`ApplicationContext`。如果有注解`@Service`的 Dubbo 服务 bean 被子上下文扫描到,这个 Dubbo`ServiceBean`也会被初始化,并且不能保证其依赖的 Spring bean 在那个时候已经准备好 ## 解决方式 ### 方式一(已验证) 将`FeignClient`使用`ApplicationContextAware`进行获取 #### 首先写一个SpringBean获取工具类 ```java @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; } } ``` #### 通过Util获取FeignClient而不是Spring注入的方式 ```java FeignClient client = SpringContextUtils.getBean(FeignClient.class) ``` ### 方式二 升级dubbo版本至2.7.9 据说在2.7.9解决了改问题 ### 方式三 一个不完美的解决方法是,让FeignClient以懒注入的方式进行注入 ```java @Service(registry = "dubbo-registry", interfaceClass = DubboProvideFacade.class) public class DubboProviderServiceImpl implements DubboProvideFacade { @Resource @Lazy private FeignClient feignClient; ······ } ``` 最后修改:2023 年 01 月 13 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 0 如果觉得我的文章对你有用,请随意赞赏