Skip to content

ClassPathScanningCandidateComponentProvider doesn't respect AnnotationTypeFilter [SPR-12802] #17399

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

Closed
spring-projects-issues opened this issue Mar 10, 2015 · 5 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) status: declined A suggestion or change that we don't feel we should currently apply

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented Mar 10, 2015

Diego Plentz opened SPR-12802 and commented

ClassPathScanningCandidateComponentProvider doesn't find interfaces when used with AnnotationTypeFilter. AnnotationTypeFilter has a constructor that explicitly says that it can be used to find annotated interfaces:

public AnnotationTypeFilter(Class<? extends Annotation> annotationType,
boolean considerMetaAnnotations,
boolean considerInterfaces)
Create a new AnnotationTypeFilter for the given annotation type.
Parameters:
annotationType - the annotation type to match
considerMetaAnnotations - whether to also match on meta-annotations
considerInterfaces - whether to also match interfaces

But, since ClassPathScanningCandidateComponentProvider implementation filter interfaces out in the isCandidateComponent(AnnotatedBeanDefinition beanDefinition) method, the type filter doesn't work as expected.

ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider();
provider.addIncludeFilter(new AnnotationTypeFilter(MyCustomAnnotation.class, false, true));
Set<BeanDefinition> findCandidateComponents = provider.findCandidateComponents("com.foo");

Affects: 4.1.5

Issue Links:

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Mar 11, 2015

Juergen Hoeller commented

At this point, that mechanism works as designed: Our component scanning can only register concrete component classes with an application context, since the bean factory would not know what to do with them otherwise. What would you expect to happen to registered interfaces in your scenario?

Currently, specified type filters are allowed to select based on simple criteria, with non-concrete classes automatically filtered out still. So we can't simply refine that check in existing branches of the framework, otherwise some existing type filter configurations might break.

That said, we are considering a revision of the component scanning contract to allow for registering abstract component types, including interfaces, in combination with a mechanism which allows for transforming such components to usable bean classes: see #16286.

Juergen

@spring-projects-issues
Copy link
Collaborator Author

Diego Plentz commented

Juergen,

I understand that this behaviour is the one expected when registering interfaces for Spring context, but this class is being used by users(me included - and you can quickly find a lot of others users in a quick google search) to scan the classpath, since it's a better dependency to have then https://code.google.com/p/reflections/, if you're already using spring in your project.

The onde thing that isn't really clear to me is why that AnnotationTypeFilter's constructor exists since ClassPathScanningCandidateComponentProvider always remove the non-concrete interfaces anyway.

@spring-projects-issues spring-projects-issues added type: bug A general bug status: declined A suggestion or change that we don't feel we should currently apply in: core Issues in core modules (aop, beans, core, context, expression) labels Jan 11, 2019
@spring-projects-issues spring-projects-issues removed the type: bug A general bug label Jan 12, 2019
@joeltoby
Copy link

joeltoby commented May 2, 2019

I agree that the current behaviour of ignoring AnnotationTypeFilters is not intuitive or helpful since developers are using ClassPathScanningCandidateComponentProvider exactly as Diego Plentz outlined.

Is there now (several years later) any better way to filter ClassPathScanning by annotations? If not, would you consider reopening this please @jhoeller ?

@sinogermany
Copy link

@joeltoby and whoever is looking for a temp solution before #16286 gets merged:

ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false) {
    @Override
    protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
        return super.isCandidateComponent(beanDefinition) || beanDefinition.getMetadata().isAbstract();
    }
};

@joeltoby
Copy link

joeltoby commented Dec 3, 2019

Thank you @sinogermany. I'll give that a try!

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: declined A suggestion or change that we don't feel we should currently apply
Projects
None yet
Development

No branches or pull requests

4 participants