【问题标题】:How to avoid changing a bean name during refactoring if it's injected with @Autowired + @Qualifier如果使用@Autowired + @Qualifier 注入,如何避免在重构期间更改 bean 名称
【发布时间】:2018-12-04 15:48:10
【问题描述】:

默认情况下,使用 @Component 注释的 bean 可以通过首字母小写的短类名来解析,例如class x.y.z.Foo -> "foo"。如果我们有多个 bean 实现相同的接口,则应通过 @Qualifier 注释指定注入的 bean,如 @Qualifier("foo")

但是,在重构时,bean 可以从 Foo 重命名为 Bar 并且 @Qualifier 中的所有引用都应相应地从 @Qualifier("foo") 重命名为 @Qualifier("bar"),否则,我们会收到错误运行时。

有没有一种方法可以在运行前促进对此类 bean 的搜索,或者至少获得编译时错误或警告?

我现在看到的最好的方法是创建一个注册表类并将所有 bean 名称保留在那里:

public final class BeanNames {
     public static final String FOO = "foo";
     ...
}

@Component(BeanNames.FOO)
class Foo { ... }

class Baz {
   @Autowired
   @Qualifier(BeanNames.FOO)
   Foo foo;
   ...

【问题讨论】:

  • 我的问题:为什么要对代码进行如此剧烈的命名更改,以至于以前名为“foo”的 bean 将被称为“bar”?
  • 即使你重构了 bean,它也应该可以在不重命名限定符内的值的情况下工作。另一种方法是自动装配接口而不是自动装配实现的类。
  • @Makoto 如果类名稍有变化(例如,它只是一个错字的修复),情况会更糟,因为你可以很容易地在 @Qualifier 中忽略它
  • @NawnitSen 1) 如果您重命名注入的 bean,则不会。 2)自动装配实现的类导致紧密耦合

标签: java spring spring-boot dependency-injection


【解决方案1】:

您可以创建基于标准 @Qualifier 的自定义限定符注释:

@Target({ElementType.CONSTRUCTOR, ElementType.FIELD,
         ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface QualifierFoo {}

然后用它注释你的组件类:

@Component
@QualifierFoo
class Foo { ... }

并像任何其他带有限定符的 bean 一样注入它:

class Baz {
   @Autowired
   @QualifierFoo
   Foo foo;
   ...

然后,当您将Foo 重构为Bar 时,您所需要做的就是将限定符名称从QualifierFoo 重构为QualifierBar

【讨论】:

    猜你喜欢
    • 2020-03-21
    • 1970-01-01
    • 1970-01-01
    • 2013-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-02
    • 2019-09-28
    相关资源
    最近更新 更多