[spring-projects/spring-boot]当配置属性扫描和组件扫描都为同一类创建 bean 时改进诊断

2024-04-10 557 views
4

问题 将 Spring Boot 升级到版本2.2.0.M2(来自2.2.0.M1)后,用 注释的 bean@ConfigurationProperties被加载两次,导致应用程序失败并出现以下异常 -

Parameter 0 of constructor in config.HazelcastConfiguration required a single bean, but 2 were found:
    - hazelcastProperties: defined in file [D:\LocationGuru\Projects\JavaEE\spring-boot-issues\target\classes\config\HazelcastProperties.class]
    - application.hazelcast-config.HazelcastProperties: defined in null

请参阅下面的应用程序日志 -

2019-04-16 20:40:51.517  INFO 14804 --- [           main] config.HazelcastProperties               : Creating bean HazelcastProperties ..
2019-04-16 20:40:51.517  INFO 14804 --- [           main] config.HazelcastProperties               : Creating bean HazelcastProperties ..
2019-04-16 20:40:51.517  INFO 14804 --- [           main] config.HazelcastConfiguration            : Found 2 HazelcastProperties beans ..

解决方法 添加@Primary到所有带有注释的类@ConfigurationProperties似乎可以暂时解决该问题。

观察 1 使用建议的解决方法,应用自动装配实例列表(如下所示),使 Spring Boot 加载 beans 两次 -

@Autowired
public HazelcastConfiguration(final List<HazelcastProperties> propertiesList)
{
    logger.info("Found {} HazelcastProperties beans ..", propertiesList.size());
}

观察 2 使用建议的解决方法应用自动装配单实例(如下所示)使 Spring Boot 加载 beans 一次(如预期)-

@Autowired
public HazelcastConfiguration(final HazelcastProperties properties)
{
    logger.info("Found 1 HazelcastProperties beans ..");
}

请参阅随附的项目(spring-boot-issues.zip)以重现该问题。

可能与 gh-15802 有关。

回答

4

几分钟前我刚刚在 #16580 中报告了同样的问题:-)

8

感谢您尝试 M2、@kedar-joshi 和 @Polve。非常感激。尽管首先创建了#16580,但我们保留这个,因为它有一个重现问题的示例。

6

问题是组件扫描和新配置属性扫描都发现了您的 bean。在短期内,删除@Component将为您的配置属性类提供一个 bean。我们需要弄清楚在 M3 中该怎么做。

1

@mbhave 提醒我这是预期的并且已记录在案。当我将配置属性扫描部分添加到发行说明中时,我错过了它。我现在就纠正它。我将保留这个开放性,以便我们可以重新审视这个决定,看看是否有办法让事情变得更加顺利。

5

我无法使用此解决方法,因为使用 @RestController 注释也会出现问题。

所以我会等待下一个里程碑来做一些测试。

3

感谢您提供额外信息,@Polve。抛开这个问题不谈,我建议你不要在同一个类上使用@RestControllerand 。@ConfigurationProperties从概念上讲,REST 控制器和配置属性是两个独立的事物,我鼓励您在类中反映这一点。

4

删除@Component对我有用。谢谢。

5

我们将看看是否可以抛出一个特定的异常来引导人们不要@Component使用@ConfigurationProperties.

1

经过一次大的重构后,我能够仅使用 @ConfigurationProperties 注释创建单独的类,但这与 2.1 不兼容,因为我需要用 @Component 来标记它们。

我在#16580和#16969中写了详细信息

7

@威尔金索纳。

我有同样的问题:

***************************
APPLICATION FAILED TO START
***************************

Description:

guru.springframework.msscbreweryclient.web.client.BreweryClient is annotated with @ConfigurationProperties and @Component. This may cause the @ConfigurationProperties bean to be registered twice.

Action:

Remove @Component from guru.springframework.msscbreweryclient.web.client.BreweryClient or consider disabling automatic @ConfigurationProperties scanning.

我正在使用 spring-boot-starter-parent 2.2.0.M4,分支是:https://gitlab.com/cviniciusm/mssc-brewery-client/tree/fail-configuration_properties-and-component

@ConfigurationProperties(value = "sfg.brewery", ignoreUnknownFields = false)
@Component
public class BreweryClient {

    private final String BEER_PATH_V1 = "/api/v1/beer/";

    private String apiHost;
@SpringBootTest
class BreweryClientTest {

    @Autowired
    BreweryClient client;
...
9

@cassiusvm 这要求您删除@Component,所以请这样做。如果这样做出现问题,请创建一个单独的问题,并使用一个小示例来演示该问题。

9

你好@snicoll,

如果我这样做,那么错误是:

Failed to bind properties under 'sfg.brewery' to guru.springframework.msscbreweryclient.web.client.BreweryClient:

    Reason: Failed to bind properties under 'sfg.brewery' to guru.springframework.msscbreweryclient.web.client.BreweryClient

在 2.1.x.RELEASE 下,错误是另一个:由于缺少注释组件,BreweryClient 未注入到 BreweryClientTest 中。

因此,我通过使用注释 ConfigurationProperties 获取另一个类 BreweryProperties 上的属性解决了这个问题,然后将最后一个注入到 BreweryClient 中。

注意:1)我确实向您展示了我的分支、解决方案,并且也有到主分支的合并; 2) 在 2.1.x.RELEASE 上,带有注释 ConfigurationProperties 和 Component 的 BreweryClient 可以成功运行。

9

@cassiusvm@ConfigurationProperties应该是独立的类,不应混合配置绑定和其他逻辑(即常规组件的功能),因此将其移动到单独的类是您首先应该做的事情。我看过你的项目,升级体验确实不太好。我创建了https://github.com/spring-projects/spring-boot/issues/17750