使用nacos+springboot2.4, 2.5+时启动提示ClassNotFount:ConfigurationBeanFactoryMetadata

使用nacos+springboot2.4, 2.5+时启动提示ClassNotFount:ConfigurationBeanFactoryMetadata,第1张

使用nacos+springboot2.4, 2.5+时启动提示ClassNotFount:ConfigurationBeanFactoryMetadata

使用nacos+springboot2.4, 2.5+时启动提示ClassNotFount:ConfigurationBeanFactorymetadata修复
      • 方案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中的解决方案

  • 将低版本 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
方案2: 既然nacos自己不修复, 那就自己动手丰衣足食

这个方法看起来复杂, 但实际上更简单, 前提要求是最好有自己的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的修复版本吧

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5684444.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存