简体   繁体   中英

How to bind a yml object to a field declared as an interface that the object implements?

I have this java hierarchy:

interface Foo {
    // methods
}

@Data
@Component
@NoArgsConstructor
class Bar implements Foo {
    // override interface methods
}

@Data
@Component
@NoArgsConstructor
class Baz implements Foo {
    // override interface methods
}

@Data
@Configuration
@EnableConfigurationProperties
@ConfigurationProperties(prefix = "foo")
class FooConfig {
    List<Foo> stuff = new Arraylist<>;
}

and this application.yml

foo:
    stuff[0]: { Bar }
    stuff[1]: { Baz }

But this does not work. I get this exception

Failed to instantiate [Foo]: Specified class is an interface

When i change List<Foo> stuff to List<Bar> stuff it only works for stuff[0]: { Bar }

You don't need any configuration properties/yml files to achieve this. Spring is intelligent enough to detect implementations of an interface.

Just do this.

@Data
@Configuration
class FooConfig {
    @Autowired
    List<Foo> stuff;
}

Spring will automagically search all the implementations of interface Foo and autowire it.

NOTE: All the implementations should be a bean(in your case you have @Component on both Bar and Baz, so it should be fine)

You can even do

@Data
@Configuration
class FooConfig {
   @Autowired
   Map<String, Foo> stuffMap;
}

In this case, spring will create a map, with key as bean names(by default it will be bar and baz)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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