Consider the following class:
public class MyBean {
private A a;
@Autowired(required=true)
public void setA(A a) {
this.a = a;
}
If you have multiple candidates for injection you can specify the default one by using @Primary on the bean you want to be the default AImpl. That way no changes are needed to MyBean
Ok here it goes, I believe this answer will satisfy your needs.
What we need is an implementation of MergedBeanDefinitionPostProcessor
that will set the correct value for the property a
of class MyBean
. This can be done by the following class
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.stereotype.Component;
@Component
public class MyBeanPostProcessor implements MergedBeanDefinitionPostProcessor {
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
if(beanName.equals("myBeanFirst")) {
beanDefinition.getPropertyValues().add("a", getMyBeanFirstAImpl());
}
else if(beanName.equals("myBeanSecond")) {
beanDefinition.getPropertyValues().add("a", getMyBeanSecondAImpl());
}
}
private Object getMyBeanFirstAImpl() {
return new AImpl();
}
private Object getMyBeanSecondAImpl() {
return new AImpl();
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
As you can see the names of the beans here are hardcoded but they could be set in static final String that would be also used by the @Bean annotations in the following code
@Configuration
public class Configuration {
@Bean
public MyBean myBeanFirst() {
return new MyBean();
}
@Bean
public MyBean myBeanSecond() {
return new MyBean();
}
}
You will notice in the following code that setA is not called in the MyBean creation methods, because no matter what value we set (or in this case don't set) will be overridden when Spring executes the bean post processor.
In case you need a default value for A (if for example you are injecting it in other beans), proceed to define a @Bean in the previous configuration
If you want myBeanFirst to use first, then just call first()
. Same for myBeanSecond, want it to use second, then just call second()
when setting A;
@Configuration
public class MyConfig {
@Bean
public A first() {
return new AImpl();
}
@Bean
public A second() {
return new AImpl();
}
@Bean
public MyBean myBeanFirst() {
MyBean myBean = new MyBean();
myBean.setA(first());
return myBean;
}
@Bean
public MyBean myBeanSecond() {
MyBean myBean = new MyBean();
myBean.setA(second());
return myBean;
}
}