Report an error
The project is based on spring-boot-2.6.3, and later needs to be connected to nacos as the registration center. After connecting to nacos, the error is reported as follows: The
error message indicates that the ConfigurationBeanFactoryMetadata class cannot be found in the running environment.
Error analysis
Judging from the error message, it is necessary to initialize the ConfigurationPropertiesRebinderAutoConfiguration Bean during the project startup process. This Bean refers to the ConfigurationBeanFactoryMetadata class, which cannot be found (NoClassDefFoundError).
First, let’s take a look at the ConfigurationBeanFactoryMetadata class. This class appears in the spring-boot package, as shown below:
However, in spring-boot-2.4.X and above, this class has been deleted.
Let’s take a look at the relevant dependency versions of the error reporting project:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.3</version>
<relativePath/>
</parent>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2.0.3.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>2.0.3.RELEASE</version>
</dependency>
The spring-boot version used in the project is 2.6.3, which means that in this version, the ConfigurationBeanFactoryMetadata class has been deleted. During the project startup process, the ConfigurationPropertiesRebinderAutoConfiguration bean is initialized (to be precise, the configurationPropertiesBeans method of initializing ConfigurationPropertiesRebinderAutoConfiguration returns bean), because the ConfigurationBeanFactoryMetadata class cannot be found, the NoClassDefFoundError error is reported.
Resolution process
There are many solutions on the Internet:
spring-boot version downgrade
This method is rough and simple. Since the ConfigurationBeanFactoryMetadata class has been deleted in versions 2.4. If this approach is adopted, the project will not be able to access the functions of the new version of spring-boot, and the project's spring-boot version will always stay at a lower version unless it waits for nacos to solve the problem in the new version. Obviously this method is very low.
Manually add ConfigurationBeanFactoryMetadata
Since the new version has deleted the org.springframework.boot.context.properties.ConfigurationBeanFactoryMetadata class, manually adding it to the project can theoretically solve this problem. Specific reference:
https://blog.csdn.net/demontxy/article/details/122187321
The solution is very simple, that is, create a new package on your own project (org.springframework.boot.context.properties is consistent with the package of ConfigurationBeanFactoryMetadata ), then create a new class ConfigurationBeanFactoryMetadata class under the package (keep it consistent with the classes in lower versions, such as spring-boot-2.3. Get this bean from:
@Bean
@ConditionalOnMissingBean(
search = SearchStrategy.CURRENT
)
public ConfigurationPropertiesBeans configurationPropertiesBeans() {
ConfigurationBeanFactoryMetadata metaData = (ConfigurationBeanFactoryMetadata)this.context.getBean(ConfigurationBeanFactoryMetadata.BEAN_NAME, ConfigurationBeanFactoryMetadata.class);
ConfigurationPropertiesBeans beans = new ConfigurationPropertiesBeans();
beans.setBeanMetaDataStore(metaData);
return beans;
}
I have tried this method, but it still reports an exception, but the error reported is NoSuchBeanDefinitionException, which means that the Spring context does not find the bean of the ConfigurationBeanFactoryMetadata class. The current guess is that the reason is caused by the bean loading order, that is to say, when initializing the configurationPropertiesBeans of ConfigurationPropertiesRebinderAutoConfiguration , applicationContext (spring context) has not initialized the bean of the ConfigurationBeanFactoryMetadata class.
Transform nacos source code
This method is generally caused by the introduction of the following nacos dependencies:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.3</version>
</parent>
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-discovery-spring-boot-starter</artifactId>
<version>0.2.7</version>
</dependency>
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-config-spring-boot-starter</artifactId>
<version>0.2.7</version>
</dependency>
spring-boot is version 2.4.X and above. After introducing nacos dependency, NoClassDefFoundError error is reported:
The specific reason is that after the project is started, when the NacosBootConfigurationPropertiesBinder bean is initialized, the bean of the ConfigurationBeanFactoryMetadata class will be fetched from the Spring context:
private ConfigurationBeanFactoryMetadata beanFactoryMetadata;
private StandardEnvironment environment = new StandardEnvironment();
public NacosBootConfigurationPropertiesBinder(ConfigurableApplicationContext applicationContext) {
super(applicationContext);
this.beanFactoryMetadata = (ConfigurationBeanFactoryMetadata)applicationContext.getBean(ConfigurationBeanFactoryMetadata.BEAN_NAME, ConfigurationBeanFactoryMetadata.class);
}
Since the spring-boot-2.6.3 version deleted the ConfigurationBeanFactoryMetadata class, a NoClassDefFoundError error will be reported.
The NacosBootConfigurationPropertiesBinder class appears in the nacos-config-spring-boot-autoconfigure dependency package:
First, you need to download the nacos-spring-boot-project source code:
Then modify the NacosBootConfigurationPropertiesBinder class. The main purpose of the modification is to replace the ConfigurationBeanFactoryMetadata class and then modify it. version number, then repackage, deploy to maven private server, and then introduce the modified version into the project. For specific modification methods, please refer to: https://blog.csdn.net/demontxy/article/details/122187321
My projects and solutions:
First, the project depends on the version:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.3</version>
<relativePath/>
</parent>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2.0.3.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>2.0.3.RELEASE</version>
</dependency>
When the project is started, a NoClassDefFoundError error is reported when initializing the configurationPropertiesBeans of ConfigurationPropertiesRebinderAutoConfiguration. The reason mentioned above is that the ConfigurationBeanFactoryMetadata class has been deleted in higher spring versions (2.4.X and above).
@Bean
@ConditionalOnMissingBean(
search = SearchStrategy.CURRENT
)
public ConfigurationPropertiesBeans configurationPropertiesBeans() {
ConfigurationBeanFactoryMetadata metaData = (ConfigurationBeanFactoryMetadata)this.context.getBean(ConfigurationBeanFactoryMetadata.BEAN_NAME, ConfigurationBeanFactoryMetadata.class);
ConfigurationPropertiesBeans beans = new ConfigurationPropertiesBeans();
beans.setBeanMetaDataStore(metaData);
return beans;
}
First, let’s take a look at the ConfigurationPropertiesRebinderAutoConfiguration class. This class comes from the spring-cloud-context-2.0.4.RELEASE package. The spring-cloud-context package comes from the spring-cloud-starter-alibaba-nacos-config dependency package:
spring -cloud-context-2.0.4.RELEASE This package version is relatively low and is adapted to the relatively low spring-boot version. For this reason, it is speculated that the dependence on the ConfigurationBeanFactoryMetadata class will be deleted in the updated spring-cloud-context package (adapted to higher spring-boot versions, such as 2.5.X), because the higher version of the spring-boot package will be deleted If the ConfigurationBeanFactoryMetadata class is installed, the spring-cloud version that is compatible with it will also remove its dependence on this class.
Based on the above ideas, to solve the NoClassDefFoundError error of the ConfigurationBeanFactoryMetadata class,
you can upgrade the versions of spring-cloud-starter-alibaba-nacos-discovery and spring-cloud-starter-alibaba-nacos-config to a higher version, such as:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2021.0.1.0</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>2021.0.1.0</version>
</dependency>
This version of the nacos package depends on the relatively high version of spring-cloud-context-3.1.1. In this version, the ConfigurationPropertiesRebinderAutoConfiguration class removes its dependence on the ConfigurationBeanFactoryMetadata class.
On the other hand, if you don’t want to upgrade the versions of spring-cloud-starter-alibaba-nacos-discovery and spring-cloud-starter-alibaba-nacos-config, you can also directly upgrade the dependency package spring-cloud-context. After all, the NoClassDefFoundError error is Because the dependency package version is too low, you can directly upgrade the spring-cloud-context version to 3.1.4.
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-context</artifactId>
<version>3.1.4</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2.0.3.RELEASE</version>
<exclusions>
<exclusion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-context</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>2.0.3.RELEASE</version>
<exclusions>
<exclusion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-context</artifactId>
</exclusion>
</exclusions>
</dependency>