Spring:注入实现接口的所有具体类的列表

pay*_*yne 0 java spring dependency-injection spring-boot

我有一个@Service类,其中包含List其他@Service类。这List基本上包含了所有的服务implements UniformEventsResearchApi

作为 Spring 的新手,我不确定如何让 Spring 允许我遵循开闭原则,从而让该列表自动注入所有具体实现。

这是一个不完整的 UML 类图:

uml类图

这是一些“代码”:

@Service
public class EventsResearchService {

    // todo: this should be Injected automatically
    private List<UniformEventsResearchApi> eventsResearchApis = Arrays.asList(new EventbriteApi());

// Already tried, but without success:
//
//    @Autowired
//    private List<UniformEventsResearchApi> eventsResearchApis2;
//
//    @Autowired
//    @Qualifier("EventsResearchApi")
//    public void setXList(List<UniformEventsResearchApi> apis) {
//        this.eventsResearchApis2 = apis;
//    }

}


@Service
@Qualifier("EventsResearchApi")
public interface UniformEventsResearchApi { /* ... */ }


public abstract class EventsResearchApi implements UniformEventsResearchApi { /* ... */ }


/** Any class like this one which extends EventsResearchApi should be automatically injected in the List */
public class EventbriteApi extends EventsResearchApi { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

Mar*_*nik 5

对于 spring 来说,这实际上是一个简单的任务:

\n\n

您可以像常规 bean 一样自动连接 bean 列表\n在这种情况下,spring 确实会找到实现该接口并注入的所有 bean:

\n\n
public interface SomeInterface {\n}\n\n@Component\npublic class SomeImpl1 implements SomeInterface {}\n\n@Component\npublic class SomeImpl2 implements SomeInterface {}\n\n@Service\npublic \xd1\x81lass SampleBean {\n\n     @Autowired\n     private List<SomeInterface> beans;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

需要注意的是,应该至少有一个可用的 beans 实现,\n否则 Spring 不会\xe2\x80\x99 不会让你这样的注入。如果您知道可能出现这种情况,您可以注入Optional<List<SomeInterface>>

\n\n

使用字段注入,它看起来相当丑陋,但您可以使用构造函数注入(无论如何更好)或考虑使用 \xe2\x80\x9cjava 配置\xe2\x80\x9d:

\n\n
@Service\npublic class SampleBean {\n   private final List<SomeInterface> beans;\n   // I haven\xe2\x80\x99t checked this with compiler, should work\n    @Autowired // optional, if you have a single constructor, you can omit it\n    public SampleBean(Optional<List<SomeInterface>> beans) {\n       this.beans = beans.orElse(Collections.emptyList());   \n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n