Spring Boot 3.4.1升级启动失败:Order注解类型转换异常排查
Java 17 + Spring Boot 3.4.1 升级后SFTP项目启动失败问题排查与解决
问题场景
将项目从Java 1.8升级到Java 17、Spring Boot 2.x升级到3.4.1后,多数项目迁移成功,但一个使用SFTP的项目无法启动。调试发现异常抛出点在org.springframework.integration.config.AbstractMethodAnnotationPostProcessor.processBeanDefinition方法第205行,代码尝试将@Order注解的Integer值转换为String类型时,触发java.lang.IllegalArgumentException(无法将Integer适配为String)。
项目配置
- Java版本:17
- spring-boot-starter-parent版本:3.4.1
- tomcat.embed.core.version:10.1.35
- spring-integration-core、spring-integration-file等集成组件使用spring-boot-starter-parent默认版本
异常触发代码片段
if (isClassIn(handlerBeanClass, Orderable.class, AbstractSimpleMessageHandlerFactoryBean.class)) { mergedAnnotations.get(Order.class) .getValue(AnnotationUtils.VALUE, String.class). ifPresent((order) -> handlerBeanDefinition.getPropertyValues().add("order", order)); }
异常栈信息
java.lang.IllegalArgumentException: Unable to adapt value of type java.lang.Integer to java.lang.String at org.springframework.core.annotation.TypeMappedAnnotation.adapt(TypeMappedAnnotation.java:483) at org.springframework.core.annotation.TypeMappedAnnotation.getValue(TypeMappedAnnotation.java:391) at org.springframework.core.annotation.TypeMappedAnnotation.getAttributeValue(TypeMappedAnnotation.java:372) at org.springframework.core.annotation.AbstractMergedAnnotation.getValue(AbstractMergedAnnotation.java:176) at org.springframework.integration.config.AbstractMethodAnnotationPostProcessor.processBeanDefinition(AbstractMethodAnnotationPostProcessor.java:205) at org.springframework.integration.config.MessagingAnnotationPostProcessor.processMessagingAnnotationOnBean(MessagingAnnotationPostProcessor.java:143) at org.springframework.integration.config.MessagingAnnotationPostProcessor.processCandidate(MessagingAnnotationPostProcessor.java:130) at org.springframework.integration.config.MessagingAnnotationPostProcessor.postProcessBeanDefinitionRegistry(MessagingAnnotationPostProcessor.java:99) at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:349) at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:148) at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:791) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:609) at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:752) at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:439) at org.springframework.boot.SpringApplication.run(SpringApplication.java:318) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1361) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1350) at com.msts.Application.main(Application.java:39)
项目pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.msts</groupId> <artifactId>transmit-file-command</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>transmit-file-command</name> <description>Transmit File</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.4.1</version> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>17</java.version> <junit-jupiter.version>5.3.2</junit-jupiter.version> <axon.version>4.10.3</axon.version> <tomcat.embed.core.version>10.1.35</tomcat.embed.core.version> </properties> <dependencies> <!-- Spring Boot 2 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-rest</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-core</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-core</artifactId> <version>${tomcat.embed.core.version}</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web-services</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> <!-- Flyway --> <dependency> <groupId>org.flywaydb</groupId> <artifactId>flyway-core</artifactId> <version>9.22.3</version> </dependency> <!-- Spring Boot with data --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!-- Axon with Spring Boot --> <dependency> <groupId>org.axonframework</groupId> <artifactId>axon-spring-boot-starter</artifactId> <version>${axon.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> </dependency> <dependency> <groupId>com.github.mwiede</groupId> <artifactId>jsch</artifactId> <version>0.2.16</version> </dependency> <!-- Postgresql DB --> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <version>42.7.2</version> </dependency> <!-- AMZON SQS --> <!-- https://mvnrepository.com/artifact/software.amazon.awssdk/sqs --> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-java-sdk-sqs</artifactId> <version>1.11.551</version> </dependency> <!-- Amazon SNS --> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-java-sdk-sns</artifactId> <version>1.11.551</version> </dependency> <!-- GSON --> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> </dependency> <!-- Json Convert --> <dependency> <groupId>org.json</groupId> <artifactId>json</artifactId> <version>[20241224,)</version> </dependency> <!-- Log back --> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> </dependency> <!-- Convert DTO to entity or viceversa --> <dependency> <groupId>org.modelmapper</groupId> <artifactId>modelmapper</artifactId> <version>2.3.2</version> </dependency> <!-- Common utils --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> </dependency> <!-- Validations utils --> <dependency> <groupId>commons-validator</groupId> <artifactId>commons-validator</artifactId> <version>1.5.0</version> </dependency> <!-- Swagger API --> <dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId> <version>2.7.0</version> </dependency> <!-- Spring Boot Test --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>junit</groupId> <artifactId>junit</artifactId> </exclusion> </exclusions> </dependency> <!-- junit 5 --> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <scope>test</scope> </dependency> <!-- Allow conditional logic in XML file --> <dependency> <groupId>org.codehaus.janino</groupId> <artifactId>janino</artifactId> </dependency> <!-- aws dynamodb --> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-java-sdk-dynamodb</artifactId> <version>1.11.661</version> </dependency> <!-- APACHE Http Client --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.14</version> </dependency> <dependency> <groupId>com.github.derjust</groupId> <artifactId>spring-data-dynamodb</artifactId> <version>5.1.0</version> </dependency> <dependency> <groupId>org.springframework.integration</groupId> <artifactId>spring-integration-core</artifactId> </dependency> <dependency> <groupId>org.springframework.integration</groupId> <artifactId>spring-integration-file</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-integration</artifactId> </dependency> <!-- Spring FTP --> <dependency> <groupId>org.springframework.integration</groupId> <artifactId>spring-integration-ftp</artifactId> </dependency> <dependency> <groupId>org.springframework.integration</groupId> <artifactId>spring-integration-sftp</artifactId> </dependency> <!-- Spring SFTP --> <!-- <dependency> <groupId>org.springframework.integration</groupId> <artifactId>spring-integration-sftp</artifactId> </dependency> --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> </dependency> <!-- Flatfile parser --> <dependency> <groupId>com.github.ffpojo</groupId> <artifactId>ffpojo</artifactId> <version>1.0</version> </dependency> <!--login check --> <dependency> <groupId>commons-net</groupId> <artifactId>commons-net</artifactId> <version>3.6</version> </dependency> <!-- https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api --> <dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> <version>2.3.1</version> </dependency> <!-- https://mvnrepository.com/artifact/javax.activation/activation --> <dependency> <groupId>javax.activation</groupId> <artifactId>activation</artifactId> <version>1.1</version> </dependency> <!-- https://mvnrepository.com/artifact/org.glassfish.jaxb/jaxb-runtime --> <dependency> <groupId>org.glassfish.jaxb</groupId> <artifactId>jaxb-runtime</artifactId> <version>2.3.1</version> <!-- Use the latest version available --> </dependency> <dependency> <groupId>com.opencsv</groupId> <artifactId>opencsv</artifactId> <version>4.1</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-csv</artifactId> <version>2.11.1</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.11.1</version> </dependency> <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.13.2</version> </dependency> <!-- https://mvnrepository.com/artifact/software.amazon.awssdk/secretsmanager --> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-java-sdk-secretsmanager</artifactId> <version>1.11.339</version> </dependency> <!-- Maven example --> <dependency> <groupId>org.liquibase</groupId> <artifactId>liquibase-core</artifactId> <version>4.25.1</version> </dependency> </dependencies> <build> <finalName>transmit-file-command</finalName> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <addResources>true</addResources> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> </plugin> <plugin> <groupId>org.flywaydb</groupId> <artifactId>flyway-maven-plugin</artifactId> <version>9.22.3</version> </plugin> </plugins> </build> </project>
问题原因分析
- Spring Integration核心bug:Spring Boot 3.4.1集成的Spring Integration版本中,
AbstractMethodAnnotationPostProcessor的代码逻辑错误——@Order注解的value属性本身是int类型,但代码强行指定String.class作为目标类型去获取值,而Spring的注解值适配机制不支持Integer到String的直接转换,导致抛出类型转换异常。 - 依赖版本冲突隐患:pom.xml中存在多处依赖版本不一致问题(如Jackson的2.11.1和2.13.2版本共存),以及使用了javax.的JAXB旧依赖(Spring Boot 3.x已迁移到Jakarta EE规范,对应依赖应为jakarta.),这些虽然不是直接触发启动失败的原因,但会引发其他潜在问题。
解决方案
1. 修复Spring Integration核心bug
Spring Integration 6.2.5及以上版本已修复该类型转换问题,可通过两种方式升级:
- 方式一:升级Spring Boot版本:将spring-boot-starter-parent版本升级到3.4.2及以上,新版本会自动集成修复后的Spring Integration版本。
- 方式二:显式指定Spring Integration版本:在pom.xml的properties中添加版本配置:
<properties> <spring-integration.version>6.2.5</spring-integration.version> </properties>
2. 清理依赖冲突与适配Jakarta规范
- 替换JAXB依赖:移除javax.xml.bind、javax.activation等旧依赖,替换为Jakarta EE对应的依赖:
<dependency> <groupId>jakarta.xml.bind</groupId> <artifactId>jakarta.xml.bind-api</artifactId> </dependency> <dependency> <groupId>org.glassfish.jaxb</groupId> <artifactId>jaxb-runtime</artifactId> <scope>runtime</scope> </dependency> - 统一Jackson版本:移除所有Jackson依赖的显式version标签,让Spring Boot parent统一管理版本,避免版本不一致:
<dependency> <groupId>
相关产品推荐
相关产品推荐

