繁体   English   中英

即使在 spring 中使用限定符,也会调用 Autowire 构造函数两次

[英]Autowire constructor is called twice even using Qualifier in spring

我正在尝试使用 spring 中的限定符来学习自动装配,并且自动装配的 class 构造函数被调用了两次。 我有以下 class:

主应用:

public class MainApp {
    public static void main(String[] args) {
//        ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
        ApplicationContext ctx =
                new AnnotationConfigApplicationContext(HelloWorldConfig.class);
//        TextEditor obj = (TextEditor) ctx.getBean("helloWorld");
        TextEditor obj = (TextEditor)ctx.getBean(TextEditor.class);
        obj.spellCheck();

    }

拼写检查器:

public class SpellChecker {
    public SpellChecker() {
        System.out.println("Inside SpellChecker constructor.");
    }

    public void checkSpelling() {
        System.out.println("Inside checkSpelling.");
    }

文本编辑器

public class TextEditor {

    @Qualifier("a")
    @Autowired
    private SpellChecker spellChecker;

    public SpellChecker getSpellChecker( ) {
        return spellChecker;
    }
    public void spellCheck() {
        spellChecker.checkSpelling();
    }
}

我有基于 java 的配置,它有多个具有相同类型的 bean,并且想要 select 一个带有限定符的 bean,但是 output 显示构造函数被调用了两次。

HelloWorldConfig

@Component
public class HelloWorldConfig {
    @Bean
    public HelloWorld helloWorld(){
        return new HelloWorld();
    }
    @Bean
    public TextEditor textEditor(){
        return new TextEditor();
    }
    @Bean(name="a")
    public SpellChecker spellChecker(){
        return new SpellChecker();
    }
    @Bean(name="b")
    public SpellChecker spellChecker1(){
        return new SpellChecker();
    }
}

OUTPUT:

Inside SpellChecker constructor.
Inside SpellChecker constructor.
Inside checkSpelling.

我期待一个 SpellChecker 构造函数调用,因为我使用 Qualifier("a") 来指定 bean,但是即使我使用 Qualifier 到 select 单个 bean,构造函数也会被调用两次。 为什么叫两次??

查看HelloWorldConfig文件。 您已经声明了 2 个 SpellChecker 类型的 bean:

@Bean(name="a")
public SpellChecker spellChecker(){
    return new SpellChecker();
}
@Bean(name="b")    
public SpellChecker spellChecker1(){
   return new SpellChecker();
}

这两个 bean 都是由 spring 创建的,尽管只有一个 bean 被注入到TextEditor中。

在 spring 中,拥有多个相同类型的 bean 或实现相同接口的 bean 完全没问题(想想监听器 - 可能有很多) - 所以 spring 容器将在应用程序启动期间创建它们。

但是,如果您想将其中一个 bean 注入另一个 bean(例如您的情况下的TextEditor ), spring 将不知道要注入哪个 bean,这就是您添加“限定符”功能的原因。

另请注意,您错误地在配置 class 上放置了@Component注释,而不是您应该使用@Configuration注释来指定此 class 包含一系列 bean 定义(您确实使用@Bean注释声明)。 尽管“配置”也是一个组件(由 spring 管理) - spring 仍然以与普通 bean 截然不同的方式对待它。

还有一个注意事项:虽然它与您的问题没有直接关系,但您似乎在您提供的代码片段中混合了 2 styles 配置: @Qualifier/@Autowired的样式(这种方式已添加到 spring 2.5如果我没记错的话)和 java 配置的风格: @Configuration class 和@Bean -s 在里面。

您可以完全避免使用自动装配,并通过从 java 配置调用的构造函数注入依赖项,如下所示:

@Configuration
public class HelloWorldConfig {
    @Bean
    public HelloWorld helloWorld(){
        return new HelloWorld();
    }
    @Bean
    public TextEditor textEditor(@Qualifier("a") SpellChecker spellChecker){ // note the dependency here
        return new TextEditor(spellChecker);
    }
    @Bean(name="a")
    public SpellChecker spellChecker(){
        return new SpellChecker();
    }
    @Bean(name="b")
    public SpellChecker spellChecker1(){
        return new SpellChecker();
    }
}

// the TextEditor Class should have a constructor with one argument:

public class TextEditor {
  private final SpellChecker spellChecker;
  public TextEditor(SpellChecker spellChecker) {
     this.spellChecker = spellChecker;
  }
  ...
}

// or if you use lombok library:

@AllArgsConstructor
public class TextEditor {
  private final SpellChecker spellChecker;
  ...
}

现在请注意,您的“业务类”甚至不知道 spring 所有“分辨率”(使用限定符和注入规则)都是在 spring 配置中完成的,无论如何这是一个特殊的 ZA2F2ED4F8EBC2CBB4C21A29DC4。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM