Affects: SpringBoot 3.1.0
i am using @Configuration(enforceUniqueMethods = false)
to allow the configuration has the save name of beans, but if i set sync: false
,it show the error Parameter 0 of method xxx required a bean of type xxx that could not be found.
.
it only execute the code which is on the top, for example i put the SyncFlatMessageHandlerImpl
bean on the top of AsyncFlatMessageHandlerImpl
and set sync: true
,it also show the error Parameter 0 of method xxx required a bean of type xxx that could not be found.
. because it did not execute the code in AsyncFlatMessageHandlerImpl
@Configuration(enforceUniqueMethods = false)
public class RabbitMqClientAutoConfiguration {
@Bean
@ConditionalOnProperty(value = "sync", havingValue = "true", matchIfMissing = true)
public MessageHandler messageHandler() {
return new AsyncFlatMessageHandlerImpl();
}
@Bean
@ConditionalOnProperty(value = "sync", havingValue = "false")
public MessageHandler messageHandler() {
return new SyncFlatMessageHandlerImpl();
}
@Bean(initMethod = "start", destroyMethod = "stop")
public RabbitMqCanalClient rabbitMqCanalClient(MessageHandler messageHandler) {
.......
return rabbitMqCanalClient;
}
}
Comment From: mdeinum
This isn't allowed in Java regardless of what the enforceUniqueMethods
states. You cannot have 2 methods with the exact same signature in a Java class.
The enforceUniqueMethods
is there when you have methods with the same name but different signatures (like including a different dependent dependency), to eliminate errors with this it can be enforced to differentiate the names (which is the default).
Comment From: bclozel
As highlighted by @mdeinum, this is not a valid code snippet. @wang-xiaowu Please provide a minimal sample application that reproduces this issue.
Comment From: wang-xiaowu
As highlighted by @mdeinum, this is not a valid code snippet. @wang-xiaowu Please provide a minimal sample application that reproduces this issue.
plz look this demo https://github.com/wang-xiaowu/demo1
Comment From: snicoll
I am not sure how it's related to enforceUniqueMethods
. It looks like the identity of the thing that matches the condition is not separate between the first, and the second method. Looking at the auto-configuration report, we get this:
UserConfig#user:
Did not match:
- @ConditionalOnProperty (sync=true) found different value in property 'sync' (OnPropertyCondition)
Matched:
- @ConditionalOnProperty (sync=false) matched (OnPropertyCondition)
As a result, the bean is not created at all. If I specify a bean name this still fails which is a bit strange.
Comment From: quaff
Here is refined test case:
package com.example.demo;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import com.example.demo.ApplicationTests.Config.UserBean;
@SpringBootTest
public class ApplicationTests {
@Autowired
private ApplicationContext ctx;
@Test
void test() {
ctx.getBean(UserBean.class);
}
@Configuration(enforceUniqueMethods = false)
static class Config {
@Bean
@ConditionalOnProperty(value = "sync", havingValue = "true", matchIfMissing = true)
UserBean user(Environment env) {
return new UserBean.User1();
}
@Bean
@ConditionalOnProperty(value = "sync", havingValue = "false")
UserBean user() {
return new UserBean.User2();
}
@Bean
String pet() {
return "pet";
}
public static class UserBean {
static class User1 extends UserBean {
}
static class User2 extends UserBean {
}
}
}
}
plugins {
id "java"
id "org.springframework.boot" version "3.1.0"
id "io.spring.dependency-management" version "1.1.0"
}
group = "com.example"
version = "0.0.1-SNAPSHOT"
sourceCompatibility = "17"
repositories {
mavenCentral()
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter")
testImplementation("org.springframework.boot:spring-boot-starter-test")
}
tasks.named("test") {
useJUnitPlatform()
}
Although the pet
bean is not used by others, It's very weird that entire pet()
method must be removed not just comment out @Bean
to pass the tests.
Comment From: wang-xiaowu
is there a deadline or version for this problem to be revoled?
Comment From: snicoll
I am afraid there isn't. I would argue that there is nothing blocking you really as using the same method name is not recommended. You could refactor your code to have dedicated method names (as they should) and that would allow you to move forward.
Comment From: wang-xiaowu
yes,that is what i am doing but do we have a plan of supporting this condition?
Comment From: jhoeller
We intend to deprecate the use of overloaded @Bean
factory methods, enforcing unique method names instead: #31073
It's not just condition declarations, it's any kind of metadata that looks like it is specific to the declared method while in reality it is part of a bean definition that potentially delegates to several factory methods. Distinct bean definitions with distinct metadata need to have distinct bean names, otherwise it is a semantic mess and also a mess in terms of readability.