Spring

末鹿安然 提交于 2020-02-26 07:38:25

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.

public abstract class Animal { ... }
@Component
public class MyDog extends Animal { ... }
@Component
public class MyCat extends Animal { ... }
@Component
public class MyBird extends Animal { ... }

The question is - how to register all my animals?

@Component
public class AnimalRegistry {
    private Map<String, Animal> registry;
    
    // How to register all my animals to the registry?
}

Naive Approach

@Component
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

@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

@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

public inteface Provider { ... }
@Component
public class DogProvider implements Provider { ... }
@Component
public class CatProvider implements Provider { ... }
@Component
public class BirdProvider implements Provider { ... }
@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));
        }
    }
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!