-
Notifications
You must be signed in to change notification settings - Fork 38.5k
Convenient programmatic bean retrieval with qualifiers [SPR-8891] #13532
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
Comments
Chris Beams commented Hi Ilya, It's actually quite rare that one would want to fetch a bean by qualifier from the From the look of the StackOverflow thread, your use case appears to be an isolated one; that is, it doesn't seem represent a common and general-purpose need. We tend to be as conservative as possible about adding to the public API in Spring, and in this case, as 'axtavt' mentioned, it can be done, but it takes a few lines of code instead of just one. That's probably a good tradeoff in this particular case. Of course, if other users have use cases around bean retrieval by qualifier, we can revisit this. For now, resolving this issue as "won't fix". In any case, however, thanks for the submission. Thanks, Chris |
Vasil Yordanov commented I'm reopening this issue, because I don't think this is an isolated case. Does spring framework offer such kind of services? |
Oliver Drotbohm commented In Spring Data, we've just introduced |
Dave Syer commented There are some newish convenience methods in private <T> List<T> provide(ListableBeanFactory factory, Class<T> type,
String... qualifiers) {
List<T> list = new ArrayList<>();
for (String name : factory.getBeanNamesForType(type)) {
if (BeanFactoryAnnotationUtils.isQualifierMatch(value -> {
for (String qualifer : qualifiers) {
if (!qualifer.equals(value))
return false;
}
return true;
}, name, factory)) {
list.add(factory.getBean(name, type));
}
}
return list;
} |
Dave Syer commented It's still ugly though. See here for gorey details: spring-projects/spring-boot#14657. The main issue is that you have to force the bean definition to resolve its factory method using a dummy private static <T> List<T> beans(AutowireCapableBeanFactory beanFactory,
Class<T> type, String qualifier) {
List<T> list = new ArrayList<>();
if (!(beanFactory instanceof ListableBeanFactory)) {
return list;
}
ListableBeanFactory listable = (ListableBeanFactory) beanFactory;
for (String name : listable.getBeanNamesForType(type)) {
if (listable instanceof DefaultListableBeanFactory) {
// Force bean definition to resolve its factory method
Field dummy = ReflectionUtils.findField(Factory.class,
"genericConverters");
((DefaultListableBeanFactory) listable).isAutowireCandidate(name,
new DependencyDescriptor(dummy, false));
}
if (BeanFactoryAnnotationUtils.isQualifierMatch(
(value) -> qualifier.equals(value), name, listable)) {
list.add(listable.getBean(name, type));
}
}
return list;
} The dummy field is not needed in the Also inconvenient is that there is no way to detect a "bare" if (targetAnnotation != null && targetAnnotation.equals(annotation)) {
return true;
} |
Juergen Hoeller commented Dave Syer, I'll see what I can do for 5.1.1 still. Essentially, all you need right now is an API for reliably finding all matching beans by type plus qualifier? |
Dave Syer commented Yes, what we need is feature parity for functional registration with |
Juergen Hoeller commented I'm not sure feature parity should be a goal here since some of those annotation-based variants only really make sense in the fully annotation-based context and are less than ideal in a programmatic world. Just like As for registering qualifiers on a That said, what we can certainly do for 5.1.1 is consistent internal resolution of the factory method (since this should be transparent to the outside when using |
Juergen Hoeller commented I've added a |
Dave Syer commented Thanks, that's useful. There's no way to match "anonymous" |
Juergen Hoeller commented I've added a variant of my previous approach: We store a factory method candidate for introspection purposes in a separate field now, not influencing the constructor resolution algorithm itself. This should not cause any regressions again and nevertheless address your case, Dave Syer. Please give it one more try! |
Dave Syer commented It works and spring-projects/spring-boot#14657 was merged. Thanks. |
Ilya Kazakevich opened SPR-8891 and commented
Because of http://stackoverflow.com/questions/8345723/java-spring-tagging-beans-in-xml-to-get-specific-bean-by-class-and-tag I need to find bean which is an instance of specific interface and has special qualifier.
Spring needs to have something like this: beanFactory.getBean(new NameCondition("someName"), new ClassCondition(MyInterface.class));
beanFactory.getBean(new QualifierCondition("myQualif"), new ClassCondition(MyInterface.class));
beanFactory.getBean(new ClassCondition(MyInterface.class));
getBean should be vararg method that accepts several conditions and joins them using "AND".
Issue Links:
@Around
/@Before
/ ...1 votes, 10 watchers
The text was updated successfully, but these errors were encountered: