Home > database >  Create specific bean dependant on property
Create specific bean dependant on property

Time:02-10

Lets say i have two beans:

class MyBean implements BeanInterface(){}

class MyBean2 implements BeanInterface(){}

And if specific property exists, i want to create MyBean, otherwise I want to create MyBean2(). How can i do this?

@Bean
@ConditionalOnProperty(name = "property.validation")
public BeanInterface beanInterface() {
    return new MyBean();
}

works if I want to create MyBean if property exists, but how do I create MyBean2 if it doesn't?

@Bean
@ConditionalOnMissingBean(MyBean.class)
public BeanInterface beanInterface() {
    return new MyBean2();
}

complains that method with same name exists, and if i understand it correctly, the methods name need to be camelCase name of the bean.

How do i do this?

Thanks

//edit i tried:

@Bean
@ConditionalOnProperty(name = "property.validation")
@Order(1)
public BeanInterface beanInterface() {
    return new MyBean();
}

@Bean("beanInterface")
@ConditionalOnMissingBean(MyBean.class)
@Order(2)
public BeanInterface beanInterface() {
    return new MyBean2();
}

but it didnt work, second bean is not getting created when property is missing.

CodePudding user response:

You can specify bean name @Bean("beanInterface") then method name can be anything.

CodePudding user response:

You have Java configuration at your hands, so use that to your advantage. Not everything needs annotations to be fixed.

@Bean
public BeanInterface myBean(Environment env) {
    String validation = env.getProperty("property.validation", String.class);
    return validation != null ? new MyBean(validation) : new MyBean2();
}

The name of the method doesn't matter it can be anything you like.

CodePudding user response:

Spring and Spring boot provide a a following solution: If you need to choose one implementation of the interface at runtime, than you inject all implementations and choose appropriate one at runtime. Assuming that you have an interface DataSource with multiple implementations here is how you inject them all:

@Autowired
private List<DataSource> dataSources; 

You can read about this solution here. This is a standard solution, but I really don't like it as it is waistful to inject all implementations. So, I wrote a feature that is available as part of MgntUtils open-source library. That feature allows you to create a static factory per each interface, and once you add any implementation of that interface declared as a Bean, that implementation will be added automatically at start up into a relevant factory. So, instead of injecting all implementations in your class you at runtime take from the factory needed implementation. I think it is much more elegant solution, and it has been battle-tested and it works well. Here is Javadoc that explains the concept and has a detailed example on how to use it: Lifecycle management. Also here is the article that describes this feature in detail: Non-intrusive access to "Orphaned" Beans in Spring framework. The library is available as Maven artifact at Maven central ad also on Github including javadoc and source code. In the source code there is a working example on how to use this feature

  • Related