简体   繁体   English

Spring 根据属性创建 bean 列表

[英]Spring create list of beans based on properties

In a simple Spring boot application I have my component like this:在一个简单的 Spring 启动应用程序中,我的组件如下所示:

@Data
@Component
public class GenericHandler {
    private String path;
    private HandlerType type;
}

And my properties might look like this:我的属性可能如下所示:

my.handlers[0].path='/vol1/abc'
my.handlers[0].type='Single'
my.handlers[1].path='/vol1/dora'
my.handlers[1].type='MultiSequence'

I tried decorating with the GenericHandler-class with @ConfigurationProperties(prefix="my.handlers") and getting a list of all component instances in a service using我尝试使用带有@ConfigurationProperties(prefix="my.handlers")的GenericHandler 类进行装饰,并使用获取服务中所有组件实例的列表

@Autowired
private List<GenericHandler> handlers;

But that created just one component, ignoring the property values at all.但这只创建了一个组件,完全忽略了属性值。

How can I get one component instance per my.handlers property-entry?如何根据my.handlers属性条目获取一个组件实例?

  • You need a wrapper class你需要一个包装器 class
    @Component
    @ConfigurationProperties(prefix="my.handlers")
    @Data
    public class GenericHandlerWrapper {

      private List<GenericHandler> handlers;
      ...

    }
  • Then you can autowire the GenericHandlerWrapper然后你可以autowire GenericHandlerWrapper

Update更新

  • As @zoolway pointed out in the comments, for the properties in the question to work as it is, @ConfigurationProperties(prefix="my.handlers") should be changed to @ConfigurationProperties(prefix="my")正如@zoolway在评论中指出的那样,要使问题中的属性按原样工作,应将@ConfigurationProperties(prefix="my.handlers")更改为@ConfigurationProperties(prefix="my")

That's not possible.那是不可能的。 What can be done is this:可以做的是:

@Data
@Component
public class GenericHandler {
    private List<String> path;
    private List<HandlerType> type;
}

I dealt with a similar issue in a different manner.我以不同的方式处理了类似的问题。 I created a factory and an interface.我创建了一个工厂和一个接口。 The factory would hold different implementations of that interface In your case, GenericHandler would be your interface.工厂将持有该接口的不同实现在您的情况下, GenericHandler将是您的接口。 Then you write any number of implementations of your interface and each implementation is declared as a Component.然后你编写任意数量的接口实现,每个实现都被声明为一个组件。 So, Spring will instantiate it as bean upon a startup (you might use @Lazy(false) to force the instantiation at startup) using some infrastructure that I wrote each bean of that interface will self-insert itself into its factory.因此,Spring 将在启动时将其实例化为 bean(您可能会使用@Lazy(false)强制在启动时实例化),使用我编写的一些基础设施,该接口的每个 bean 都会自行插入到其工厂中。 Then at any part of your code in any bean, you can use the factory to access concrete implementation (base on your property "type" for example).然后在任何 bean 中代码的任何部分,您都可以使用工厂访问具体实现(例如,基于您的属性“类型”)。 The beauty is that you don't need to inject all the implementations in your bean at the time of writing but access needed implementation dynamically at run-time.美妙之处在于您不需要在编写时将所有实现注入到您的 bean 中,而是在运行时动态访问所需的实现。 I found this to be a useful pattern and created an infrastructure that does most of the work for you and published it as an Open Source library called MgntUtils.我发现这是一个有用的模式,并创建了一个为您完成大部分工作的基础架构,并将其发布为一个名为 MgntUtils 的开源库。 The detailed description of the idea (including reference to the library) could be found here .可以在此处找到该想法的详细描述(包括对库的引用)。 Also detailed explanation with examples of how to use it can be found in library Javadoc here .还可以在此处的库 Javadoc 中找到有关如何使用它的示例的详细说明。 The library is available (with source code and Javadoc) as Maven artifacts and on the Github .该库以Maven 工件Github的形式提供(带有源代码和 Javadoc)。 Also a general article about the MgntUtils library could be found here也可以在此处找到有关 MgntUtils 库的一般文章

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

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