?其中 , 我们使用 Springboot 版本是2.2.0 。
于是手动跟踪调试了下,发现某些后置处理器执行时,在解决它的依赖时,会去创建 dubbo 服务的 bean,然后就会创建 ApplicationConfig 对象了 。注意这个对象其实只是new了一下,所有属性都是默认值 , 并非来源于我们定义的 dubbo 配置文件 。
而我们定义的 dubbo 配置文件 , 是在 ApplicationConfig 中的 addIntoConfigManager 中注入的:
public abstract class AbstractConfig implements Serializable {...@PostConstructpublic void addIntoConfigManager() {ApplicationModel.getConfigManager().addConfig(this);}...}
其中,@PostConstruct 注解会由 CommonAnnotationBeanPostProcessor 这个后置处理器(继承自 InitDestroyAnnotationBeanPostProcessor)解析执行 。但很遗憾,此时它还没有被执行,因此也就没有把正确的dubbo配置注入进去,最终导致dubbo框架在校验时发现无效配置 , 继而报错 。
网上相关讨论及解决方案关于这类报错 , 网上也有不少讨论,如:
- No application config found or it's not a valid config!
- No registry config found or it's not a valid config!
- 同样的配置,2.7.3启动成功,2.7.6启动报错
自然,dubbo官方也注意到了这个问题,于是在3.x版本进行了改造,针对该问题做了优化 , 参见Dubbo 3 Spring相关优化 。
但3.x做了大量重构,如果我们不想升级,应该怎么办呢?其实根据上面提到的原因,我们可以自己定义一个后置处理器,拦截 dubbo 框架的 beans,并手动注入对应的配置 。本质上来说,将之前来不及执行的注入代码提到前面去 。这样,我们前面提到的「某些后置处理器执行时 , 在解决它的依赖时,会去创建 dubbo 服务的 bean,然后就会创建 ApplicationConfig 对象了」 , 就变成了「某些后置处理器执行时,在解决它的依赖时,会去创建 dubbo 服务的 bean , 此时会被我们自定义的后置处理器拦截,并注入对应的dubbo配置,然后就会创建正确的 ApplicationConfig 对象」 。
具体做法为:
【一个 dubbo 和 springboot 的兼容性问题】step1. 定义一个后置处理器,识别到 bean 属于 AbstractConfig 配置后,将其注入:
package com.xxx;import org.apache.dubbo.config.AbstractConfig;import org.apache.dubbo.rpc.model.ApplicationModel;import org.springframework.beans.BeansException;import org.springframework.beans.factory.config.BeanPostProcessor;public class DubboBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (bean instanceof AbstractConfig) {AbstractConfig abstractConfig = (AbstractConfig) bean;ApplicationModel.getConfigManager().addConfig(abstractConfig);}return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);}}
step2. 定义一个 Initializer,并将刚才定义的 DubboBeanPostProcessor 注入:
package com.xxx;import org.springframework.context.ApplicationContextInitializer;import org.springframework.context.ConfigurableApplicationContext;public class DubboApplicationContextInitializerimplements ApplicationContextInitializer<ConfigurableApplicationContext> {@Overridepublic void initialize(ConfigurableApplicationContext applicationContext) {applicationContext.getBeanFactory().addBeanPostProcessor(new DubboBeanPostProcessor());}}
step3. 把 DubboApplicationContextInitializer 注入到Spring框架中,可以采用多种方式 。
方式1. 直接在启动类注入:
@ImportResource(locations = {"classpath:dubbo.xml"})@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})public class Launcher extends SpringBootServletInitializer {public static void main(String[] args) {SpringApplication springApplication = new SpringApplication(Launcher.class);springApplication.addInitializers(new DubboApplicationContextInitializer());springApplication.run(args);}}方式2. 在 resources 的 META-INF 目录下配置 spring.factories 文件并写入:
org.springframework.context.ApplicationContextInitializer=com.xxx.DubboApplicationContextInitializer
推荐阅读
- 骁龙870和天玑1200哪个玩游戏更好_骁龙870和天玑1200哪个好
- 华为p50pro和荣耀magic3pro哪个好_手机区别对比
- redmi watch和小米手表color哪款更值得买?
- 指南针怎么看经纬度(经纬度与指南针是一个方向吗)
- 七 Netty 学习:NioEventLoop 对应线程的创建和启动源码说明
- [CG从零开始] 4. pyopengl 绘制一个正方形
- 荣耀magic3和华为mate40谁更值得购买?参数配置对比
- 雅诗兰黛抗蓝光眼霜和小棕瓶眼霜哪个好?一样吗
- 指南针怎么看方向红针和白针(指南针永远指向哪个方向)
- 一加手机品控做工怎么样(一加和realme哪个做工好)