简体   繁体   中英

How to ensure a set of Spring boot beans implementing an interface being first initalized before their container being initalized?

I have a set of beans both implementing an interface

@Componet
class BeanA implements interfaceA{
   public void process(){
   }
}

@Componet
class BeanB implements interfaceA{
   public void process(){
   }
}

I want to get all beans of interfaceA and apply their process methods sequentially, so I have a container to collect these beans.

@Componet
class Container{

List<interfaceA> container;

@Autowired
private ApplicationContext applicationContext;    

@PostConstruct
public void init()
{
    container=applicationCOntext.getBeansOfType(interfaceA.class).values().stream().collect(Collections.list());
    for(obj:container){
        obj.process();
    }
}

So how can I ensure Container be initialized after all beans of interfaceA, so I can get all beans of interfaceA in init() method of Container?

Or put it another way, can applicationContext.getBeansOfType always get all beans of interfaceA? what if Container get initialzed first?

By the way, Container does not have to be a componet.

You can inject a list with all the components implementing interfaceA :

@Componet
class Container{

    @Autowired
    List<interfaceA> container;

    @PostConstruct
    public void init()
    {
        for(obj : container){
            obj.process();
        }
    }
}

In such a case you don't need to worry about components creation order, Spring is smart enough to make it right.

Components scanning/initialization is a two-step process. First, Spring collects all beans definitions and builds a dependency graph (without creating any beans). After that, it knows in what order the beans should be initialized. When you inject interfaceA beans as a list, Spring knows, that the Container instance depends on them and will initialize them first. It wouldn't be the case if you obtained the components manually from the ApplicationContext (the dependency would be hidden) and you would need @DependsOn annotations on the interfaceA components.

  1. You can use @DependsOn(value = {"beanA", "beanB"}) on you Container class.

  2. And Make your Container class implement InitializingBean interface and override the afterPropertiesSet() method.

  3. And then move the logic that you've written in init method to afterPropertiesSet() method.

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