Andres Almiray opened SPR-12929 and commented

Currently the ApplicationContext is capable of resolving beans and beans names given an annotation but the reverse is not, that is, obtain an annotation given a bean name.

Currently annotation metadata is harvested and stored in org.springframework.core.type.AnnotationMetadata but the actual annotation is not.

For reference, this feature was discussed with Jürgen at Voxxed Days Ticino 2015 in the context of a generic, external JSR-330 compatible API on top of Spring and Guice.


Affects: 4.1.6

Issue Links: - #17723 Support dynamic bean lookup a la CDI's Instance type - #13532 Convenient programmatic bean retrieval with qualifiers

2 votes, 4 watchers

Comment From: spring-projects-issues

Andres Almiray commented

Harvesting qualifier information related to a bean or a set of beans can be done in the following way (a bit cumbersome but possible)

AutowireCapableBeanFactory autowireCapableBeanFactory = appContext.getAutowireCapableBeanFactory();
if (autowireCapableBeanFactory instanceof BeanDefinitionRegistry) {
    BeanDefinitionRegistry beanDefinitionRegistry = (BeanDefinitionRegistry) autowireCapableBeanFactory;
    for (String beanDefinitionName : appContext.getBeanNamesForType(type)) {
        BeanDefinition beanDefinition = beanDefinitionRegistry.getBeanDefinition(beanDefinitionName);
        AnnotatedGenericBeanDefinition agbd = (AnnotatedGenericBeanDefinition) beanDefinition;
        AutowireCandidateQualifier qualifier = null;
        Set<AutowireCandidateQualifier> qualifiers = agbd.getQualifiers();
        if (qualifiers != null && qualifiers.size() > 0) {
            qualifier = qualifiers.iterator().next();
        }
        AnnotationMetadata metadata = agbd.getMetadata();
        // ???
    }
}

Two problems appear here: 1. one must rely on explicit implementations (such as BeanDefinitionRegistry and AnnotatedGenericBeanDefinition) to reach the annotation metadata. 2. AnnotationMetadata contains all information pertaining qualifiers but does not have a link to the annotations that provided such information.

I wish it was possible to reach out for AnnotationMetadata directly from a BeanDefinition instance.

Comment From: spring-projects-issues

Juergen Hoeller commented

I'm afraid it's even less natural for Spring 5 to store and expose annotation instances than before. We do intend to introduce new retrieval facilities but primarily for functional-style filtering: #13532. Internally, we remain rather agnostic to annotation instances and process specific annotation metadata for our purposes only, which I'd like to keep up.

Rather than downcasting BeanDefinitions, a call getType for each such bean name returns a Class which can be introspected for type-level annotations meta-annotated with @Qualifier (or the like). Admittedly, this won't work for qualifiers on @Bean methods; is this the missing part here? How does the corresponding lookup work for Guice?

Comment From: spring-projects-issues

Andres Almiray commented

In Guice, every com.google.inject.Binding is referenced by a com.google.inject.Key that contains the injection type and an optional annotation. A Key matches the type and annotation at a point of injection. Say you want to define a bean of type Person annotated with @Named, you could do it in the following way inside a Module:

public class MyModule extends AbstractModule {
  public void configure(Binder binder) {
    binder.bind(Person.class)
              .annotatedWith(Named.class);
  }
}

In a sense, explicit Module configuration in Guice is similar to Spring's Java config via @Configuration and @Bean. Guice also supports "on-demand" bindings, that is, if a type is required but is not defined by a Module, and if the type can be found then an implicit binding is created. this is similar to Spring's @Component support.

Being able to query annotations that may have been defined in the target type (option # 2 via @Component) and in the config class (option # 1 via @Bean) is exactly what I need to write a "native" Spring based injector that can define bindings programmatically and harvest existing types/annotations. My current workaround to support Spring on Grifofn is to leverate spring-guice https://github.com/spring-projects/spring-guice This project wraps an ApplicationContext within a Module. As the documentation says it does not cover all cases and registers all beans eagerly.

Comment From: SaiKrishnaKaushik

Hi Is this still a requirement and there is a need for it?