【问题标题】:Bean name resolution in Spring using @Bean and @Qualifier annotations在 Spring 中使用 @Bean 和 @Qualifier 注解解析 Bean 名称
【发布时间】:2020-03-21 22:17:52
【问题描述】:

我刚刚发现了我无法理解的 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()
    }
}

然后,我有一个类应该使用名为 exceptionalRestTemplate 的 bean。

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

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

原来问题出在在配置类中声明 bean 的方法的名称上。两者都收集regularRestTemplate。更改第二个方法名,解决问题。

我的问题是,为什么?我知道 Spring 使用带有 @Bean@Component@Service 等注释的类和方法的名称来为解析图中的 Java 对象命名。但是,我认为在这些注释中命名会覆盖这种行为。

有人告诉我发生了什么事吗?

【问题讨论】:

  • 这些方法用作工厂方法,在ConfigurationClassBeanDefinitionReader 中对此进行了特殊处理。在 2 个单独的 @Configuration 带注释的类中执行此操作。

标签: java spring spring-boot dependency-injection


【解决方案1】:

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

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

spring.main.allow-bean-definition-overriding=true

然后重新启动您的应用程序。之后,您将只有第二个 bean。

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

【讨论】:

  • 感谢您的回复。你有没有参考官方文档?
  • 不。只是经验和观察。
  • 这个答案实际上是错误的,因为这个问题与@Qualifierbean name 无关。正如@m-denium 指出的那样,在同一个@Configuration 类中存在同名bean 工厂方法的问题。上下文实际上将有两个bean,每个bean 都有自己的名称和限定符,但两者都将使用相同的工厂方法(两个regularRestTemplate(..) 方法之一)创建,因为其中一个在ConfigurationClassBeanDefinitionReader 工作期间丢失。所以,预选赛工作正常。这是错误的bean创建。对我来说似乎是一个错误(或者您可以将其命名为“专业”,呵呵)。
  • 根据Spring documentation bean 名称被认为是默认限定符值。 bean 定义中没有指定限定符,因此在这种特殊情况下限定符和名称是一模一样。
猜你喜欢
  • 2012-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-31
  • 2017-04-24
  • 2018-08-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多