简体   繁体   中英

Injecting Collection of Interface Type into Method Annotated with @Bean

Using Spring and given several classes that implement a common interface, how would I reference all classes that implemented this interface using the @Bean annotation at the method level?

I want to retrieve all implementing instances, apply some logic to each instance, then return a managed Map<String, Animal> object which can be injected to other classes or components.

Common Interface(s)

public interface Animal {

   String makeNoise();

}
public interface Person {

   String getOccupation();

}

Animal Implementation #1

public Dog implements Animal {

   @Override
   String makeNoise() {
      return "Bark! Bark!";
   }

} 

Animal Implementation #2

public Cat implements Animal {

   @Override
   String makeNoise() {
      return "Meow! Meow!";
   }

} 

Person Implementation #1

public Developer implements Person {

   @Override
   public String getOccupation() {
      return "Software Engineer";
   }

}

Person Implementation #2

public Lawyer implements Person {

   @Override
   public String getOccupation() {
      return "Litigator";
   }

}

Configuration

@Configuration
public class Initialize {

   //<snip> Beans created for Developer, and Lawyer objects </snip>

   @Bean
   Map<String, Developer> getDevelopers(List<Developer> developers) { // This is fine
      return new HashMap<>(...);
   }

   @Bean
   Map<String, Lawyer> getLawyers(List<Person> people) { // Spring wires this dependency fine
      return new HashMap<>(...);
   }

   @Bean
   Map<String, Dog> getOwners(Map<String, Person> owners) { // Spring reports it cannot auto-wire this dependency
                                                            // what do I do here? 
   }

}

Any help would be appreciated, thanks!

Try this kind of configuration. The only point here is that the order of beans in the collection is random and can't be under control.

    @Configuration
    public class CollectionConfig {

        @Bean
        public Animal getCat() {
            return new Cat();
        }

        @Bean
        public Animal getDog() {
            return new Dog();
        }

        @Bean
        Map<String, Animals> gatherAnimals(List<Animals> animals) {
           // any code
        }
    }

Here is more about that https://www.baeldung.com/spring-injecting-collections

Need to leverage co-variance with a List . See below pseudo-code/code snippet.

@Configuration
public class Initialize {

   //<snip> Beans created for Developer, and Lawyer objects </snip>

   @Bean
   Map<String, Developer> getDevelopers(List<Developer> developers) {
      return new HashMap<>(...);
   }

   @Bean
   Map<String, Lawyer> getLawyers(List<Person> people) {
      return new HashMap<>(...);
   }

   @Bean
   Map<String, Dog> getOwners(List<Map<String, ? extends Person>> owners) { // Spring will auto-wire the "owners" variable 
                                                                            // with all bean objects that match this signature 
                                                                            // (✅ Map<String, Lawyer>, ✅ Map<String, Developer> ...)

   }

}

Resources:

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