Issue
Is there any way to get both of these beans instantiated:
@Bean
@ConditionalOnMissingBean
public Container<Book> bookContainer() {
return new Container<>(new Book());
}
@Bean
@ConditionalOnMissingBean
public Container<Computer> computerContainer() {
return new Container<>(new Computer());
}
@ConditionalOnMissingBean
only takes the bean class into account, falsely making bookContainer
and computerContainer
the same type, thus only one of them gets registered.
I could give explicit qualifiers to each, but since this is a part of a Spring Boot Starter, it would make it annoying to use, as the user would then be forced to somehow know the exact name to override instead of the type only.
Potential approach:
Since it is possible to ask Spring for a bean by its full generic type, I might be able to implement a conditional factory that will try to get a fully-typed instance and produce one if it doesn't already exist. I'm now investigating if/how this can be done.
Amazingly, when implementing a custom condition (to be used with @Conditional
), it does not have access to the bean type...
While every other modern injection framework operates on full types, Spring somehow still works with raw classes and string names(!) which just blows my mind... Is there any workaround for this?
Solution
It's possible since Spring Boot v2.1.0.
That version introduced the new field parameterizedContainer
on ConditionalOnMissingBean
.
@Bean
@ConditionalOnMissingBean(value = Book.class, parameterizedContainer = Container.class)
public Container<Book> bookContainer() {
return new Container<>(new Book());
}
@Bean
@ConditionalOnMissingBean(value = Computer.class, parameterizedContainer = Container.class)
public Container<Computer> computerContainer() {
return new Container<>(new Computer());
}
Answered By - Sven Döring
Answer Checked By - Clifford M. (JavaFixing Volunteer)