spring – @autowired for list types Have Spring Autowire All Subclass Better Usage of @Autowired This tip should work well w.r.t interfaces

How to use Spring to autowire list types? How to autowired all subclasses of a parent class, or all implementations of an interface.

Let’s see an example - we have three pets that we’d like to register them on the public animal registry.

1
public abstract class  { ... }
1
2

public class MyDog extends { ... }
1
2

public class MyCat extends { ... }
1
2

public class MyBird extends { ... }

The question is - how to register all my animals?

1
2
3
4
5
6

public class AnimalRegistry {
private Map<String, Animal> registry;


}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

public class AnimalRegistry {
private Registry<Animal> registry;

/**
* This is naive because if you have more animals,
* you have to specify them explicitly here
*/
@Autowired
public AnimalRegistry (MyDog dog, MyCat cat, MyBird bird){
registry.register(dog);
registry.register(cat);
registry.register(bird);
}
}

Have Spring Autowire All Subclass

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Component
public class AnimalRegistry {
private Registry<Animal> registry;

/**
* The problem with this approach is that
* if you don't have any animals, there's no bean to be autowired here,
* and Spring will report bean initialization error
*/
@Autowired
public AnimalRegistry (List<Animal> myAnimals){
if(myAnimals != null && !myAnimals.isEmpty()) {
myAnimals.forEach(a -> registry.register(a));
}
}
}

Better Usage of @Autowired

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Component
public class AnimalRegistry {
private Registry<Animal> registry;

@Autowired(required = false)
List<Animal> myAnimals;

/**
* This ensures that Spring can still successfully run
* even when there's no bean to be autowired to 'myAnimals'
*/
@PostConstruct
public void init() {
if(myAnimals != null && !myAnimals.isEmpty()) {
myAnimals.forEach(a -> registry.register(a));
}
}
}

This tip should work well w.r.t interfaces

1
public inteface Provider { ... }
1
2
@Component
public class DogProvider implements Provider { ... }
1
2
@Component
public class CatProvider implements Provider { ... }
1
2
@Component
public class BirdProvider implements Provider { ... }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Component
public class ProviderRegistry {
private Registry<Provider> registry;

@Autowired(required = false)
List<Provider> providers;

@PostConstruct
public void init() {
if(providers != null && !providers.isEmpty()) {
providers.forEach(a -> registry.register(a));
}
}
}