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

@ComponentScan(includeFilters=@Filter(...)) fails when @Import'ed [SPR-8719] #13361

Closed
spring-projects-issues opened this issue Sep 23, 2011 · 3 comments
Labels
in: core Issues in core modules (aop, beans, core, context, expression) status: duplicate A duplicate of another issue

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented Sep 23, 2011

Stepan Koltsov opened SPR-8719 and commented

@ComponentScan does not work in @Import-ed configuration.

public class Coin { }

public class Main {

    @Configuration
    @ComponentScan(basePackageClasses = Main.class,
            useDefaultFilters = false,
            includeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = Coin.class))
    public static class Conf1 {
    }

    @Configuration
    @Import(Conf1.class)
    public static class Conf2 {

    }

    public static void main(String[] args) {
        System.out.println("loading Conf1"); // works fine
        new AnnotationConfigApplicationContext(Conf1.class).getBean(Coin.class);

        System.out.println("loading Conf2"); // cannot find a bean
        new AnnotationConfigApplicationContext(Conf2.class).getBean(Coin.class);
        System.out.println("Unreachable in Spring 3.1.0.M2");
    }

}

Outputs:

loading Conf1
loading Conf2
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [ru.yandex.commune.junk.stepancheg.spring.shinderuk.Coin] is defined: expected single bean but found 0: 
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:269)
	at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1101)
	at ru.yandex.commune.junk.stepancheg.spring.shinderuk.Main.main(Main.java:31)

Probably related to #12956.


Affects: 3.1 M2

Issue Links:

Referenced from: commits d9f7fdd

2 votes, 0 watchers

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Nov 23, 2011

Chris Beams commented

Stepan, I'm looking into this, but just FYI, it's ultimately the same cause here as #12634, which you filed.

It's not actually that @ComponentScan does not work on @Imported @Configuration classes, it's that @ComponentScan annotations that use nested @Filter annotations cause problems.

It's a bit of a sticky problem, but I'll see if a fix is possible for RC2

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Nov 23, 2011

Chris Beams commented

See comments re: ASM on #12634

@spring-projects-issues
Copy link
Collaborator Author

Chris Beams commented

commit d9f7fdd120409fff4491561215e5b2dda74e2b02
Author: Chris Beams <cbeams@vmware.com>
Date:   Wed Apr 6 15:41:08 2011 +0800

    Support reading nested annotations via ASM
    
    Background
    
      Spring 3.1 introduced the @ComponentScan annotation, which can accept
      an optional array of include and/or exclude @Filter annotations, e.g.
    
         @ComponentScan(
             basePackages = "com.acme.app",
             includeFilters = { @Filter(MyStereotype.class), ... }
         )
         @Configuration
         public class AppConfig { ... }
    
      @ComponentScan and other annotations related to @Configuration class
      processing such as @Import, @ImportResource and the @Enable*
      annotations are parsed using reflection in certain code paths, e.g.
      when registered directly against AnnotationConfigApplicationContext,
      and via ASM in other code paths, e.g. when a @Configuration class is
      discovered via an XML bean definition or when included via the
      @Import annotation.
    
      The ASM-based approach is designed to avoid premature classloading of
      user types and is instrumental in providing tooling support (STS, etc).
    
      Prior to this commit, the ASM-based routines for reading annotation
      attributes were unable to recurse into nested annotations, such as in
      the @Filter example above. Prior to Spring 3.1 this was not a problem,
      because prior to @ComponentScan, there were no cases of nested
      annotations in the framework.
    
      This limitation manifested itself in cases where users encounter
      the ASM-based annotation parsing code paths AND declare
      @ComponentScan annotations with explicit nested @Filter annotations.
      In these cases, the 'includeFilters' and 'excludeFilters' attributes
      are simply empty where they should be populated, causing the framework
      to ignore the filter directives and provide incorrect results from
      component scanning.
    
      The purpose of this change then, is to introduce the capability on the
      ASM side to recurse into nested annotations and annotation arrays. The
      challenge in doing so is that the nested annotations themselves cannot
      be realized as annotation instances, so must be represented as a
      nested Map (or, as described below, the new AnnotationAttributes type).
    
      Furthermore, the reflection-based annotation parsing must also be
      updated to treat nested annotations in a similar fashion; even though
      the reflection-based approach has no problem accessing nested
      annotations (it just works out of the box), for substitutability
      against the AnnotationMetadata SPI, both ASM- and reflection-based
      implementations should return the same results in any case. Therefore,
      the reflection-based StandardAnnotationMetadata has also been updated
      with an optional 'nestedAnnotationsAsMap' constructor argument that is
      false by default to preserve compatibility in the rare case that
      StandardAnnotationMetadata is being used outside the core framework.
      Within the framework, all uses of StandardAnnotationMetadata have been
      updated to set this new flag to true, meaning that nested annotation
      results will be consistent regardless the parsing approach used.
    
      Spr9031Tests corners this bug and demonstrates that nested @Filter
      annotations can be parsed and read in both the ASM- and
      reflection-based paths.
    
    Major changes
    
     - AnnotationAttributes has been introduced as a concrete
       LinkedHashMap<String, Object> to be used anywhere annotation
       attributes are accessed, providing error reporting on attribute
       lookup and convenient type-safe access to common annotation types
       such as String, String[], boolean, int, and nested annotation and
       annotation arrays, with the latter two also returned as
       AnnotationAttributes instances.
    
     - AnnotationUtils#getAnnotationAttributes methods now return
       AnnotationAttributes instances, even though for binary compatibility
       the signatures of these methods have been preserved as returning
       Map<String, Object>.
    
     - AnnotationAttributes#forMap provides a convenient mechanism for
       adapting any Map<String, Object> into an AnnotationAttributes
       instance. In the case that the Map is already actually of
       type AnnotationAttributes, it is simply casted and returned.
       Otherwise, the map is supplied to the AnnotationAttributes(Map)
       constructor and wrapped in common collections style.
    
     - The protected MetadataUtils#attributesFor(Metadata, Class) provides
       further convenience in the many locations throughout the
       .context.annotation packagage that depend on annotation attribute
       introspection.
    
     - ASM-based core.type.classreading package reworked
    
       Specifically, AnnotationAttributesReadingVisitor has been enhanced to
       support recursive reading of annotations and annotation arrays, for
       example in @ComponentScan's nested array of @Filter annotations,
       ensuring that nested AnnotationAttributes objects are populated as
       described above.
    
       AnnotationAttributesReadingVisitor has also been refactored for
       clarity, being broken up into several additional ASM
       AnnotationVisitor implementations. Given that all types are
       package-private here, these changes represent no risk to binary
       compatibility.
    
     - Reflection-based StandardAnnotationMetadata updated
    
       As described above, the 'nestedAnnotationsAsMap' constructor argument
       has been added, and all framework-internal uses of this class have
       been updated to set this flag to true.
    
    Issue: SPR-7979, SPR-8719, SPR-9031

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) status: duplicate A duplicate of another issue
Projects
None yet
Development

No branches or pull requests

1 participant