Oleksandr
Oleksandr

Reputation: 3744

How to add a bean dependency from another module in Spring?

I have two modules: module1 and module2.
module2 depends on module1.

Configuration in the module1:

@Configuration
public class ConfigurationInModule1 {

    @Bean
    public FirstBean firstBean() {
        return new FirstBean();
    }

    @Bean
    public SecondBean secondBean(FirstBean firstBean) {
        return new SecondBean(firstBean);
    }
}

Configuration in the module2:

@Configuration
public class ConfigurationInModule2 {

    @Bean
    public SomeBeanForModule2 beanForModule2(FirstBean firstBean) {
        return new SomeBeanForModule2(firstBean);
    }
}

As you can see both beans secondBean and beanForModule2 depends on firstBean. I need to make sure that when the project is compiled with module2 then beanForModule2 should be initialized before secondBean. If there is no module2 then secondBean should be initialized in a standard flow.

Is it possible to configure it in Spring?

P.S. I need to control the order of been initialization. I know that there is a special annotation @DependsOn which can be used to setup indirect dependency, but in my case I cannot use it on secondBean because the dependency beanForModule2 is optional and is placed in another module.

Upvotes: 1

Views: 6604

Answers (2)

Oleksandr
Oleksandr

Reputation: 3744

Found the solution by using BeanFactoryPostProcessor. We need to define our custom BeanFactoryPostProcessor and setup necessary dependencies there. Spring won't execute beans initialization before calling postProcessBeanFactory method.
To solve the above problem we should define our custom BeanFactoryPostProcessor like this one:

public class JBCDependencyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

        BeanDefinition beanDefinition = beanFactory.getBeanDefinition("secondBean");
        beanDefinition.setDependsOn("beanForModule2");
    }

}

After that we should make a static bean with our BeanFactoryPostProcessor. Something like this:

@Configuration
public class ConfigurationInModule2 {

    @Bean
    public static BeanFactoryPostProcessor dependencyBeanFactoryPostProcessor() {
        return new JBCDependencyBeanFactoryPostProcessor();
    }

    @Bean
    public SomeBeanForModule2 beanForModule2(FirstBean firstBean) {
        return new SomeBeanForModule2(firstBean);
    }
}

Spring will search for all beans. Then it will execute postProcessBeanFactory in our BeanFactoryPostProcessor. We will make a dependency from secondBean to beanForModule2 and then spring will call bean initialization by following our dependencies.

P.S. Thanks to @Tarun for sharing the link.

Upvotes: 1

Tarun
Tarun

Reputation: 986

Spring takes care of order of bean initialization, So if one bean depends on other then Spring will first initialize dependency Beans then it will initialize dependent Beans.
In your case FirstBean will always initialize prior than SomeBeanForModule2 without any additional config.

And if Dependency Bean which is FirstBean in your case is not declared(i.e module1 is not there) then Spring will throw org.springframework.beans.factory.NoSuchBeanDefinitionException. So module2 cannot initialized without module1.

EDIT:- For Ordering of Bean Initialization, you can use @DependsOn even if Beans are in seperate File.

Just add @import(ConfigurationInModule2.class) in ConfigurationInModule1 class in your module1.
And use @DependsOn("beanForModule2") on secondBean.

This will help:- https://stackoverflow.com/a/16297827/4720870

Upvotes: 1

Related Questions