Spring 中使用 @Bean 和 @Qualifier 注释的 Bean 名称解析

ric*_*din 4 java spring dependency-injection spring-boot

我刚刚发现了一种我无法理解的 Spring 行为。我正在使用 Spring Boot 1.5.x。

在一个配置类中,我声明了两个不同的 bean。

@Configuration
class Config {
    @Bean("regularRestTemplate")
    public RestTemplate regularRestTemplate(String toLog) {
        return new RestTemplateBuilder().setConnectTimeout(100)
                                        .setReadTimeout(100)
                                        .additionalInterceptors((request, body, execution) -> {
                                            log.info("Inside the interceptor {}", toLog);
                                            return execution.execute(request, body);
                                        })
                                        .build();
    }
    @Bean("exceptionalRestTemplate")
    public RestTemplate regularRestTemplate() {
        return new RestTemplateBuilder().setConnectTimeout(100)
                                        .setReadTimeout(100)
                                        .build()
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,我有一个类应该使用名为exceptionalRestTemplate.

@Component
class Client {
    private RestTemplate restTemplate;
    @Autowired
    public Client(@Qualifier("exceptionalRestTemplate") RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }
    // Code that uses the injected rest template
}
Run Code Online (Sandbox Code Playgroud)

由于我使用@Qualifier注释指定了要注入的 bean 的名称,因此我希望Spring 注入名为exceptionalRestTemplate. 但是,调用的beanregularRestTemplate实际上是在注入过程中使用的。

事实证明,问题在于在配置类中声明 bean 的方法的名称。两者都已收集regularRestTemplate。更改第二个方法名,解决问题。

我的问题是,为什么?我知道,Spring使用与注解的类和方法的名称@Bean或与@Component@Service等...注释给一个名称解析映射中的Java对象。但是,我认为在这些注释中命名会覆盖这种行为。

有人告诉我这是怎么回事吗?

小智 5

bean 限定符和 bean 名称是不同的含义。您对 new bean 进行了限定,但试图覆盖它(参数无关紧要)。在您的应用程序中,您不能覆盖 bean,因此您只有第一个 bean。

你可以检查这个“理论”。在您的配置中添加一个参数

spring.main.allow-bean-definition-overriding=true
Run Code Online (Sandbox Code Playgroud)

并再次启动您的应用程序。在那之后,您将只有第二个豆子。

这是对碰撞的解释。但解决方案是将 bean 分离为不同的配置。