spring-framework
spring-framework copied to clipboard
Add typesafe method to get generic bean by name with type reference
Related to GH-34669, but it requires the bean name matched first, and throw BeanNotOfRequiredTypeException if the bean type doesn't match required type from type reference.
Take codes in Spring Batch for example:
@SuppressWarnings("unchecked")
ItemReader<CustomerCredit> outputReader = (ItemReader<CustomerCredit>) applicationContext
.getBean("outputTestReader");
I'd like it could be rewrite to:
ItemReader<CustomerCredit> outputReader = applicationContext.getBean("outputTestReader", new ParameterizedTypeReference<>() {});
Here is prototype: https://github.com/spring-projects/spring-framework/compare/main...quaff:spring-framework:patch-112?expand=1
I'd like to create PR if the proposal is accepted.
Any chance target it in 7.0?
This is effectively a duplicate of the just reopened #31444, so I'll close it as such. We are about to introduce getBeanProvider(ParameterizedTypeReference) for 7.0 RC1; no getBean overloads though since those do not have ResolvableType variant either.
This is effectively a duplicate of the just reopened #31444, so I'll close it as such. We are about to introduce
getBeanProvider(ParameterizedTypeReference)for 7.0 RC1; nogetBeanoverloads though since those do not haveResolvableTypevariant either.
I don't think it's duplicate of #31444, this issue requests adding new variant of getBean(name, requiredType) not getBean(requiredType) (#34669), it get bean by name, and type safe for generic type. @jhoeller
This is effectively a duplicate of the just reopened #31444, so I'll close it as such. We are about to introduce
getBeanProvider(ParameterizedTypeReference)for 7.0 RC1; nogetBeanoverloads though since those do not haveResolvableTypevariant either.I don't think it's duplicate of #31444, this issue requests adding new variant of
getBean(name, requiredType)notgetBean(requiredType)(#34669), it get bean by name, and type safe for generic type. @jhoeller
@jhoeller Please consider to reopen it.
@quaff indeed, I mistook it as a duplicate while it is rather a related issue.
As for this specific case, we don't have getBean(name, requiredType) overloads for ResolvableType either, so we'd have to add both that and a ParameterizedTypeReference overload.
However, since that type does not have lookup semantics, just cast semantics, I wonder whether we wouldn't be better off providing a variant of getBean(name) that declares an unconditional T return type which accepts any assignment to a typed variable on the left-hand side, for example <T> T getTypedBean(String name). No assignability check of our own then, just an optimistic assignment that leads to a runtime cast by the JVM if not actually assignable.
FWIW at some point we had that in a separate convenience adapter (see https://docs.spring.io/spring-framework/docs/2.5.x/javadoc-api/org/springframework/beans/factory/generic/GenericBeanFactoryAccessor.html) but never rolled it into the main BeanFactory interface.
On review, such a T-bound lookup by name only really saves a cast but does not provide an actual type check. Maybe it's more practical to provide a getBean(name, ParameterizedTypeReference) method indeed - and no ResolvableType variant either since that relies on a T-bound return value as well, driven by the result assignment and not by the argument-provided type.
However, an explicit generic type check - just for type safety - is somewhat expensive. For a lookup by name, that's actually the most expensive part since the lookup itself is just a hash retrieval. To some degree it does seem attractive to leave that up to the JVM when it performs the cast for the result assignment.
However, an explicit generic type check - just for type safety - is somewhat expensive. For a lookup by name, that's actually the most expensive part since the lookup itself is just a hash retrieval. To some degree it does seem attractive to leave that up to the JVM when it performs the cast for the result assignment.
The most important thing is that BeanNotOfRequiredTypeException should be thrown like getBean(String name, Class<T> requiredType), application could catch BeanNotOfRequiredTypeException immediately, not later ClassCastException on actual use.
I've created #35808 to fix it, please review.
Superseded by PR #35808. Let's work on the PR toward 7.1 M1 (which we aim to release in April).