将项目从 Spring Boot v2.7 迁移到 v3.0(从而从 Spring Integration v5.5 迁移到 v6.0)后,会打印出以下警告:
WARN 22084 --- [ restartedMain] ocalVariableTableParameterNameDiscoverer : Using deprecated '-debug' fallback for parameter name resolution. Compile the affected code with '-parameters' instead or avoid its introspection: com.foobar.MyClassA
WARN 22084 --- [ restartedMain] ocalVariableTableParameterNameDiscoverer : Using deprecated '-debug' fallback for parameter name resolution. Compile the affected code with '-parameters' instead or avoid its introspection: com.foobar.MyClassB
WARN 22084 --- [ restartedMain] ocalVariableTableParameterNameDiscoverer : Using deprecated '-debug' fallback for parameter name resolution. Compile the affected code with '-parameters' instead or avoid its introspection: com.foobar.MyClassC
WARN 22084 --- [ restartedMain] ocalVariableTableParameterNameDiscoverer : Using deprecated '-debug' fallback for parameter name resolution. Compile the affected code with '-parameters' instead or avoid its introspection: com.foobar.MyClassD
MyClassA
扩展了 IntegrationFlowAdapter
,并用 @Component
: 进行注释
package com.foobar;
@Component
class MyClassA extends IntegrationFlowAdapter {
// …
}
MyClassB
注释为 @ConfigurationProperties
:
package com.foobar;
@ConfigurationProperties("my-config")
class MyClassB {
// …
}
MyClassC
注释为 @Configuration
:
package com.foobar;
@Configuration
class MyClassC {
// …
}
这个特定的甚至没有扩展任何东西,也没有注释:
package com.foobar;
class MyClassD {
// …
}
我在Spring Boot和Spring Integration迁移指南中没有看到任何相关信息。 Spring Boot迁移指南中有一个关于名称解析的部分,但它与Gradle相关,而我使用的是Maven。我什至不确定这个名称解析是关于什么的。
我对课程感到困惑
LocalVariableTableParameterNameDiscoverer
,我不知道我应该做什么迁移任务。
正如@m-deinum在问题评论中指出的那样,问题与Spring Boot或Spring Integration无关,而是与Spring Framework本身有关。我需要将 -parameters
选项添加到
javac
。如果您使用 Maven,在
pom.xml
中添加以下内容应该可以解决问题:
<project>
<!-- … -->
<build>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<parameters>true</parameters>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<!-- … -->
</project>
answer 提供了正确的修复方法,但我想展示一些代码来解释为什么会发生这种情况。
给出以下@Configuration类:
@Configuration
public class AppConfig {
@Bean
public SomeBean someBean(FooBar foo, FooBar bar) {
return new SomeBean(foo, bar);
}
@Bean
public FooBar foo() {
return new FooBar();
}
@Bean
public FooBar bar() {
return new FooBar();
}
}
创建 bean someBean
时,Spring 必须知道为
someBean()
方法的两个参数中的每一个使用哪些 bean。它通过查看方法的参数名称(即
foo
和
bar
)并将其与现有 bean 的名称进行比较来实现此目的。已弃用的LocalVariableTableParameterNameDiscoverer 用于解析方法的参数名称。 但是,只有在将
-debug
标志传递给
javac
编译器时,参数名称才会在 Java 类编译后保留。默认情况下,Maven 编译器插件会将此标志传递给 javac。这就是为什么
LocalVariableTableParameterNameDiscoverer
可以完成其工作以及发出警告的原因。使用上面的代码,可以尝试更改 Maven 编译器插件的配置,以不将调试标志传递给 javac:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<debug>false</debug>
</configuration>
</plugin>
</plugins>
</build>
编译并执行应用程序后,警告将被错误取代:
引起:org.springframework.beans.factory.NoUniqueBeanDefinitionException:没有可用的“edu.self.nyg.example.app.FooBar”类型的合格 bean:预期单个匹配 bean,但发现 2:foo,bar对于要在编译后保留的参数名称而不使用调试标志,必须使用
-parameters
标志。这将允许 Spring 的StandardReflectionParameterNameDiscoverer 替换
LocalVariableTableParameterNameDiscoverer
并正确找到
someBean()
的 foo 和 bar 参数的正确 bean。似乎建议使用
-parameters
,但要消除警告,如果需要,还可以执行以下操作:
@Bean
public SomeBean someBean(
@Qualifier("foo") FooBar foo,
@Qualifier("bar") FooBar bar) {
return new SomeBean(foo, bar);
}
请注意,将调试和参数标志都设置为 true 是可以的,Spring 将使用 StandardReflectionParameterNameDiscoverer
并且不会发出警告。
https://github.com/spring-projects/spring-framework/issues/29563。
是的,Spring Integration 使用LocalVariableTableParameterNameDiscoverer
中的
MessagePublishingInterceptor
来将方法参数作为 SpEL 中的
@Publisher
变量
PublisherMetadataSource.ARGUMENT_MAP_VARIABLE_NAME
:https://docs.spring.io/spring-integration /docs/current/reference/html/message-publishing.html#message-publishing
.另一个是
EvaluationContext
,如果您没有为该注释提供 @MessagingGateway
属性,我们会尝试从
@Header
方法参数解析标头名称:https://docs.spring.io/spring-integration /docs/current/reference/html/messaging-endpoints.html#mapping-method-arguments
name
中存在类似的逻辑来解析 POJO 服务方法的标头名称:https://docs.spring.io/spring-integration/docs/current/reference/html/configuration.html#annotations
因此,我们需要来自 Spring Integration 配置的更多信息来确定您可能需要在方法参数的MessagingMethodInvokerHelper
注释中添加 name
属性的位置。
我还看到这个
@Header
在 LocalVariableTableParameterNameDiscoverer
中已被弃用。请针对 Spring Integration 提出 GH 问题,以便我们修复它以支持上述
6.0.1
。