Spring Boot here. I have dozens and dozens of classes that are all subclass/implementations of the same interface:
public interface AnimalService {
void eat();
// etc.
}
@Component
public class DogService implements AnimalService {
@Override
public void eat() { return ... }
// etc.
}
// many many many of these
I have a @Service
-annotated class (AnimalService
) that needs to be injected with each one of these subclasses:
@Service
public class AnimalProcessingService {
@Autowired
private List<AnimalService> allAnimalServices; // DogService, SharkService, etc.
// the rest of the class definition is omitted intentionally
}
Now I could do this injection the hard way:
@Configuration
public class AnimalConfig {
private DogService dogService;
private SharkService sharkService;
// ...etc.
@Bean
public List<AnimalService> allAnimalServices() {
return Arrays.asList(dogService, sharkService /*, ...etc. */);
}
}
But there's gotta be an easier way to do this, right?
How can inject this List<AnimalService>
without having to manually create the list? Does this method allow you to filter out certain candidates (like if I just want a subset of the animal services)? Ideally something annotation-based (even if I have to define my own annotations) that works with Spring autowiring/DI/component scanning. Thanks for any and all help here!
CodePudding user response:
Essentially you're looking for @ComponentScan
, which is a Spring (not Boot) annotation. It allows you to define a list of packages for Spring to scan for @Components
(or "sub-annotations" such as @Service
), to automatically instantiate beans of those classes and add them to the Spring context. So you can consider it a more automated way of the more manual @Bean
method declaration.
Since you're using Spring Boot, however, you might want to look into @SpringBootApplication
which, when used, enables component scan automatically. All you have to do is making sure your @Component
classes are defined in the same package as, or sub-packages of, the @SpringBootApplication
-annotated class.
Once you've enabled component scanning, you can just inject a List<AnimalService>
where you need it, like in a constructor, and do your processing (filtering?) there.