如何注入供应商类型的bean?

How to inject bean of type Supplier?

我有如下代码

public class A {
@Inject
private Supplier<Set<String>> set;
.
.
}

我正在为此 class 编写测试用例,我的单元测试如下所示:

@Test(groups = "MyApp.unit")
public class ATest extends someOtherClass {

    @Inject
    private A a;

&我的单位配置看起来像

@Configuration
@Import({someClass.class})
public class UnitTestConfig {
...
 @Bean
    public Supplier<Set<String>> set() {
        Supplier<Set<String>> items = () -> Sets.newHashSet("100");
        return items;
    }

@Bean
    public A a() {
        return new A();
    }


}

我无法将 Supplier bean 注入我的 class A。已放置调试点并尝试测试,它进入了 bean 功能,但 Supplier class 没有创建。它给出消息“Class 没有字段”

所有其他 bean 似乎都很好。有人对此有任何见解吗?

如果您已经在使用 @Configuration 配置 bean,为什么不使用构造函数注入?

我建议你重写 A class 如下:

public class A {
    private final Supplier<Set<String>> sup;

    public A(Supplier<Set<String>> sup) {
        this.sup = sup;
    }
}

现在您可以使用以下选项之一:

@Configuration
public class SampleConfig {
    @Bean
    public Supplier<Set<String>> set () {
        return () -> Set.of("a","b", "c");
    }

    @Bean
    public A a (Supplier<Set<String>> sup) {
        return new A(sup);
    }
}

或另一种方式:

@Configuration
public class SampleConfig {
    @Bean
    public Supplier<Set<String>> set () {
        return () -> Set.of("a","b", "c");
    }

    @Bean
    public A a () {
        return new A(set());
    }  
}

在第二个选项中,我将 set() 称为常规方法。 Spring 处理用 @Configuration 注释的 classes,因此它是用于注入的“特殊”调用。 由于供应商是单例,因此多次调用此 set 方法(例如,来自不同的 bean)将 return 供应商的同一实例。

虽然第一种方法更灵活,因为它允许在不同的配置文件中保留供应商和 class A 的定义,第二种方法假设它们都在同一个 @Configuration.

更新(根据 Op 的评论)

对于字段注入,它的工作原理是一样的:

public class A {

    @Autowired
    private Supplier<Set<String>> sup;

    public Set<String> getSet() {
        return this.sup.get();
    }

}
@Configuration
public class SampleConfig {
    @Bean
    public Supplier<Set<String>> set () {
        return () -> Set.of("a","b", "c");
    }

    @Bean
    public A a () {
        return new A();
    }

    // this is called right before the application gets started (after all the injections are done - this is just for the sake of illustration)
    @EventListener(ApplicationReadyEvent.class)
    public void onReady(ApplicationReadyEvent evt) {
        A a = evt.getApplicationContext().getBean(A.class);
        System.out.println(a.getSet()); // this will return your set
    }
}