- 方案1: 既然spring删了, 那我们再加回来
- 方案2: 既然nacos自己不修复, 那就自己动手丰衣足食
最早项目是在2.1.7.release开发的, 最近有时间, 计划把框架内所有依赖都升级到较高版本, 包括springboot也拉到了2.5.6. nacos自然是0.2.10
刚完成依赖升级后, 启动提示grpc错误, 看到是nacos提示的, 查了查资料发现nacos新版本引入了grpc通讯保证稳定性, 但实际上我这里不需要, 于是降级到0.2.8, 这时候问题就来了, 启动到末尾提示ClassNotFount:ConfigurationBeanFactorymetadata
这个原因在stackoverflow找到的解决方案是添加springboot的bootstrap启动模式依赖, 尝试过, 失败.
某度上大多就说不兼容, 于是把springboot降级到2.1.x. 我心里一阵MMP, 这算什么解决方案? 不过既然知道原因是不兼容, 那应该有人提issue, 于是就跑到github的nacos去看issue, 果不其然有发现
github issue#4554
很多大神也给出了解决方案, 大体上就是springboot2.4.x删除了ConfigurationBeanFactorymetadata, 但是由于nacos是阿里的kpi项目, 人走茶凉没人维护, 所以虽然解决方案非常简单但依然没人管, 这里总结一下解决方案
方案1: 既然spring删了, 那我们再加回来将springboot2.3.x版本中的源码类 ConfigurationBeanFactorymetadata拷出来, 到自己项目里新建同名包并粘进去, 加@Component注解, 这里我先说一下, 我试过这种方法, 但还是不行, 提示ConfigurationBeanFactorymetadatabean找不到, 这里大概是beanfactory的加载机制问题, 而且感觉这种解决方案也很粗糙, 所以就没深入研究, 下面引入github中的解决方案
方案2: 既然nacos自己不修复, 那就自己动手丰衣足食
- 将低版本 spring-boot-2.3.11.RELEASE.jar 中的 ConfigurationBeanFactorymetadata 类源码建立在项目中,路径 org.springframework.boot.context.properties 与源码相同
- 在项目的spring.factories文件中配置加载项 ,通过 EnableAutoConfiguration 加载 ConfigurationBeanFactorymetadata ,配置如下org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.springframework.boot.context.properties.ConfigurationBeanFactory>metadata
- 关闭Spring Cloud与Spring Boot版本适配检查,spring.cloud.compatibility-verifier.enabled=false
这个方法看起来复杂, 但实际上更简单, 前提要求是最好有自己的maven私服, 或者需要手动变更本地仓库的jar
先到git上去下载源码: git clone https://github.com/nacos-group/nacos-spring-boot-project.git
网络环境不好, 多次尝试失败, 所以去gitee搞吧: git clone https://gitee.com/wu726/nacos-spring-boot-project.git
下载下来后用idea打开, 由于下载的master, 所以版本也就是0.2.10+了, 需要先回到0.2.8. 如果打算用grpc, 就需要同步更新nacos服务端, 可以用0.2.10继续. 我不想再麻烦搞服务端了, 所以通过git log, 找到0.2.8 #198版本回退回去(其实就是pom的依赖有变更, 没发现其他的什么有更新的.)
找到nacos-spring-boot-parent下的pom.xml文件, 修改38行所有springboot依赖到自己项目差不多的版本, 我这里修改为2.5.6
(有maven私服执行此步骤)修改根目录下的pom文件11行左右, 将revision修改为0.2.8.1(或0.2.10.1). 总之就是变动一下版本号
修改NacosBootConfigurationPropertiesBinder文件为
package com.alibaba.boot.nacos.config.binder; import com.alibaba.nacos.api.config.ConfigService; import com.alibaba.nacos.api.config.annotation.NacosConfigurationProperties; import com.alibaba.nacos.spring.context.properties.config.NacosConfigurationPropertiesBinder; import com.alibaba.nacos.spring.core.env.NacosPropertySource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.boot.context.properties.bind.Bindable; import org.springframework.boot.context.properties.bind.Binder; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.ResolvableType; import org.springframework.core.env.StandardEnvironment; import java.lang.reflect.Method; public class NacosBootConfigurationPropertiesBinder extends NacosConfigurationPropertiesBinder { private final Logger logger = LoggerFactory .getLogger(NacosBootConfigurationPropertiesBinder.class); private final ConfigurableListableBeanFactory beanFactory; private final StandardEnvironment environment = new StandardEnvironment(); public NacosBootConfigurationPropertiesBinder( ConfigurableApplicationContext applicationContext) { super(applicationContext); this.beanFactory = applicationContext.getBeanFactory(); } @Override protected void doBind(Object bean, String beanName, String dataId, String groupId, String configType, NacosConfigurationProperties properties, String content, ConfigService configService) { synchronized (this) { String name = "nacos-bootstrap-" + beanName; NacosPropertySource propertySource = new NacosPropertySource(name, dataId, groupId, content, configType); environment.getPropertySources().addLast(propertySource); Binder binder = Binder.get(environment); ResolvableType type = getBeanType(bean, beanName); Bindable> target = Bindable.of(type).withExistingValue(bean); binder.bind(properties.prefix(), target); publishBoundEvent(bean, beanName, dataId, groupId, properties, content, configService); publishmetadataEvent(bean, beanName, dataId, groupId, properties); environment.getPropertySources().remove(name); } } private ResolvableType getBeanType(Object bean, String beanName) { Method factoryMethod = this.findFactoryMethod(beanName); if (factoryMethod != null) { return ResolvableType.forMethodReturnType(factoryMethod); } return ResolvableType.forClass(bean.getClass()); } public Method findFactoryMethod(String beanName) { if (beanFactory.containsBeanDefinition(beanName)) { BeanDefinition beanDefinition = beanFactory.getMergedBeanDefinition(beanName); if (beanDefinition instanceof RootBeanDefinition) { return ((RootBeanDefinition) beanDefinition).getResolvedFactoryMethod(); } } return null; } }
- 修改NacosConfigEndpointAutoConfiguration文件将方法上的注解@ConditionalOnEnabledEndpoint 替换为@ConditionalOnAvailableEndpoint
- 修改NacosDiscoveryEndpointsAutoConfiguration的文件同上
- 执行Nacos Spring Boot Project的compile检查下有无报错之类的.
到这里基本就算完成了.
如果有maven私服, 在根pom下配置好
并在自己的maven/conf/setting.xml中配置好server, 执行deploy发布就可以, 然后将自己项目中的依赖修改为0.2.8.1就可以
如果没有maven私服, 就执行package, 将打包好的jar(nacos-config-spring-boot-actuator.jar, nacos-config-spring-boot-autoconfigure.jar, nacos-discovery-spring-boot-actuator.jar)复制到自己仓库中com/alibaba/boot并覆盖原有的jar, maven refresh一下即可, 部分高版本idea可能需要关闭重新打开index一下
到此问题就解决了.
参考git hub issue#194按照nacos的开发者所说, 近期可能会发布新版修复此问题, 但离我发帖过去半个月了也没见到消息, 不知道这个"近期"到底是啥时候, 而且还是要面临nacos升级带来的grpc问题, 所以还是自己搞0.2.8的修复版本吧
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)