Reputation: 1722
Consider the case when there are two (or more) Spring configuration classes, each returning a bean with the same name (e.g. baseBean
). Also, suppose that these config classes create other beans (e.g. anotherBean1
and anotherBean2
), which contain baseBean
instances.
Is there a way to make Spring inject the baseBean
instances created in the same configuration class?
// Beans
public abstract class BaseBean {
public abstract String getName();
}
public class Bean1 extends BaseBean {
@Override
public String getName() {
return "Bean1";
}
}
public class Bean2 extends BaseBean {
@Override
public String getName() {
return "Bean2";
}
}
// Configurations
@Configuration
public class Config1 {
@Bean
public BaseBean baseBean() {
return new Bean1();
}
@Bean
public AnotherBean anotherBean1() {
return new AnotherBean(baseBean());
}
}
@Configuration
public class Config2 {
@Bean
public BaseBean baseBean() {
return new Bean2();
}
@Bean
public AnotherBean anotherBean2() {
return new AnotherBean(baseBean());
}
}
// Main class
public class Main {
public static void main(String [] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Config1.class, Config2.class);
AnotherBean anotherBean1 = (AnotherBean) applicationContext.getBean("anotherBean1");
AnotherBean anotherBean2 = (AnotherBean) applicationContext.getBean("anotherBean2");
System.out.println(anotherBean1.baseBean.getName());
System.out.println(anotherBean2.baseBean.getName());
}
}
Expected output:
Bean1
Bean2
Actual output:
Bean2
Bean2
In other words, both Config1.anotherBean1()
and Config2.anotherBean2()
invoke Config2.baseBean()
. Instead, I would like each Config
class to invoke its own baseBean
method, i.e. Config1.anotherBean1()
should use Config1.baseBean()
(and Config2.anotherBean2()
should of course use Config2.baseBean()
).
Is there a built-in way to force this behaviour somehow, e.g with some annotation?
BeanPostProcessor
's, or other similar extension. I would like to add an already existing annotation, or some similar solution.@Primary
, @Qualifier
, etc. is not an option: while it would work in the above example, the concrete code is structured in such a way, that does not make this possible. More precisely, baseBean()
is an abstract method in an abstract base class, which is invoked by another method, anotherBean()
in the same abstract class. Concrete classes then provide implementation for baseBean
method. This means, that in the base class I obviously cannot use any qualifier to refer to baseBean
(and cannot make any of the implementations @Primary
either).public class BaseConfig {
@Bean
public abstract BaseBean baseBean();
@Bean
public AnotherBean anotherBean() {
return new AnotherBean(baseBean());
}
}
+----------------------------+
| BaseConfig |
| |
| + (abstract) baseBean() |
| + anotherBean() |
|____________________________|
/\
/__\
_________|__________
_______|_______ _______|__________
| Config1 | | Config2 |
| + baseBean() | | + baseBean() |
|_______________| |________________|
Upvotes: 1
Views: 1184
Reputation: 1892
Is there a reason that the different baseBean
need to be Spring-Managed Beans themselves?
It sounds like you're only planning on using them from within AnotherBean
so you could simply remove the @Bean
annotation from ConfigX.baseBean()
and you'd get the expected results.
Upvotes: 2