spring-framework icon indicating copy to clipboard operation
spring-framework copied to clipboard

Add typesafe method to get generic bean by name with type reference

Open quaff opened this issue 8 months ago • 1 comments

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<>() {});

quaff avatar Mar 31 '25 00:03 quaff

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.

quaff avatar Mar 31 '25 04:03 quaff

Any chance target it in 7.0?

quaff avatar Jul 04 '25 08:07 quaff

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.

jhoeller avatar Oct 15 '25 13:10 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; no getBean overloads though since those do not have ResolvableType variant 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

quaff avatar Oct 16 '25 01:10 quaff

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.

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

@jhoeller Please consider to reopen it.

quaff avatar Nov 11 '25 02:11 quaff

@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.

jhoeller avatar Nov 12 '25 09:11 jhoeller

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.

jhoeller avatar Nov 12 '25 13:11 jhoeller

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.

quaff avatar Nov 13 '25 07:11 quaff

Superseded by PR #35808. Let's work on the PR toward 7.1 M1 (which we aim to release in April).

jhoeller avatar Nov 18 '25 15:11 jhoeller