Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add generics / parameterized type support to ListableBeanFactory getBeanNamesForType/getBeansOfType methods [SPR-12147] #16761

Closed
spring-issuemaster opened this issue Sep 3, 2014 · 7 comments

Comments

Projects
None yet
2 participants
@spring-issuemaster
Copy link
Collaborator

commented Sep 3, 2014

Lari Hotari opened SPR-12147 and commented

Spring currently doesn't have a public API for finding beans based on generics type information. Generic types seem to only be supported in autowiring fields or methods (Spring blog article).

There is a discussion about this feature in the issue comments of SPR-9965 .

I'd like to have generics support in ListableBeanFactory:

String[] getBeanNamesForType(ResolvableType resolvableType);
<T> Map<String, T> getBeansOfType(Class<T> type, ResolvableType resolvableType) throws BeansException;
<T> Map<String, T> getBeansOfType(Class<T> type, ResolvableType resolvableType, boolean includeNonSingletons, boolean allowEagerInit) throws BeansException;

Affects: 4.0.6, 4.1 RC2

Issue Links:

  • #14599 Autowiring of generic types
  • #17723 Support dynamic bean lookup a la CDI's Instance type
  • #21613 Programmatic ObjectProvider retrieval through BeanFactory API
  • #18669 getBeanNamesForType(ResolvableType) does not reliably work for beans with AOP proxies
  • #19578 getBeanNamesForType(ResolvableType) doesn't match generic factory method return type for yet-to-be-created bean

Referenced from: commits b230892, 778a019

0 votes, 11 watchers

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Sep 3, 2014

Lari Hotari commented

This issue is related to #14599 .

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Sep 3, 2014

Lari Hotari commented

I'm not actually sure if ResolvableType currently support the use case I'm looking to support. I'm working on a pull request for adding Spring Boot support to Ratpack , (exact location. Ratpack uses Guava's com.google.common.reflect.TypeToken (source) for holding generics type information.
Is it possible to create org.springframework.core.ResolvableType from Guava's TypeToken information?

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Jan 2, 2015

Phil Webb commented

I think you can use ResolvableType.forType(typeToken.getType()) to do what you want. For example:

TypeToken<List<String>> typeToken = new TypeToken<List<String>>() {};
ResolvableType resolvableType = ResolvableType.forType(typeToken.getType());
System.out.println(resolvableType);
System.out.println(resolvableType.getRawClass());
System.out.println(resolvableType.resolveGeneric(0));

Will output:

java.util.List<java.lang.String>
interface java.util.List
class java.lang.String
@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Mar 17, 2015

Rob Winch commented

Perhaps I'm missing something. Is there a reason we need to add additional methods that accept a ResolvableType?

Can you just look up the beans with the following?

String[] beanNamesForType = context.getBeanNamesForType(resolvableType.resolve());
Map<String, ?> beansOfType = context.getBeansOfType(resolvableType.resolve());
Map<String, ?> beansOfTypeRefined = context.getBeansOfType(resolvableType.resolve(), includeNonSingletons, allowEagerInit);

For others looking at this issue, you don't even need Guava to resolve the generic type. You can use something like:

ResolvableType resolvableType = ResolvableType.forClassWithGenerics(List.class, String.class);
@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Mar 18, 2015

Juergen Hoeller commented

As far as I understand this issue, the intent is to pass the full generic type information to the bean factory there, analogous to introspecting a method parameter declaration. A resolve() call would preserve a substituted type variable but would lose the nested generic types since they can't be represented in the resulting Class.

Juergen

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Mar 18, 2015

Juergen Hoeller commented

I'm looking into this at the moment...

From my perspective, a getBeanNamesForType(ResolvableType) method should be entirely sufficient, since the getBeansOfType methods are just doing the bean names thing and then getBean for each resulting name. In fact, I'd actively recommend against getBeansOfType even in its present form; getBeanNamesForType plus lazy retrieval of the bean instances is usually preferable.

And with respect to the includeNonSingletons and allowEagerInit flags, those are primarily used for limited early checks on bean factory startup... For use later on, I don't see a need to expose them even. Their public availability is to some degree a historic arrangement; we don't expose them for our {{getBeanNamesForAnnotation} variants either. Lari Hotari, do you have a specific need there?

Juergen

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Mar 18, 2015

Juergen Hoeller commented

I've introduced getBeanNamesForType(resolvableType and isTypeMatch(name, resolvableType, which should be everything needed to compose generics-based retrieval logic on top. There's also a BeanFactoryUtils.beanNamesForTypeIncludingAncestors(factory, resolvableType convenience method for hierarchical checks.

I'm rather opposed to further convenience variants. I'd only add further variants for retrieval attempts that cannot be expressed any other way.

Juergen

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.