Interfaces are annotated with @Component annotation in spring IoC/DI. What could be the reason?

10,318

Annotating an interface with @Component is common for Spring classes, particularly for some Spring stereotype annotations :

package org.springframework.stereotype;
...
@Component
public @interface Service {...}

or :

package org.springframework.boot.test.context;
...
@Component
public @interface TestComponent {...}

@Component is not declared as an inherited annotation :

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Component {...}

But whatever, during loading of the context, Spring discovers beans by considering the hierarchy of the annotation declared in the candidate class.

In the org.springframework.boot.BeanDefinitionLoader class (included in the Spring Boot dependency) that loads bean definitions from underlying sources, you can see an example of org.springframework.core.annotation.AnnotationUtils.findAnnotation() that Spring uses to retrieve annotations in the whole hierarchy of the annotation:

class BeanDefinitionLoader {
 ...
 private boolean isComponent(Class<?> type) {
    // This has to be a bit of a guess. The only way to be sure that this type is
    // eligible is to make a bean definition out of it and try to instantiate it.
    if (AnnotationUtils.findAnnotation(type, Component.class) != null) {
        return true;
    }
    // Nested anonymous classes are not eligible for registration, nor are groovy
    // closures
    if (type.getName().matches(".*\\$_.*closure.*") || type.isAnonymousClass()
            || type.getConstructors() == null || type.getConstructors().length == 0) {
        return false;
    }
    return true;
 }
 ...
}

Concretely, it means as the @Service annotation is itself annotated with @Component, Spring will consider a candidate class annotated with @Service as a bean to instantiate.

So, your guesswork is right :

Classes that implement such interface will be treated as components as well.

But this works only for interfaces (such as @Service) that are Java annotations and not for plain interfaces.

For Spring classes, this way of doing makes sense (enriching actual stereotype for example) but for your own beans, using @Component for the interface rather than the implementation will not work and would bring more drawbacks than advantages :

  • it defeats in a same way the purpose of an interface that is above all a contract. It couples it to Spring and it supposes that you will always have a single implementation of the class.
    In this case, why using an interface ?

  • it scatters the reading of the class at two places while the interface doesn't need to have any Spring stereotype.

Share:
10,318
samshers
Author by

samshers

Updated on June 04, 2022

Comments

  • samshers
    samshers almost 2 years

    Some times interfaces are annotated with @Component annotation. Then my obvious reasoning was that classes that implement such interface will be treated as components as well. But if I am right that is not the case.

    So what is the purpose of @Component annotation on interfaces.

    • Tom
      Tom over 6 years
      "But if I am right that is not the case. " - Why do you assume that?
    • samshers
      samshers over 6 years
      Anyway I have tested the same. i.e Spring is not able to detect and autowire the classes that implement such interface. I had to add @Component annotation on the classes also explicitly.
    • davidxxx
      davidxxx over 6 years
      "Some times interfaces are annotated with @Component annotation." Can you give a concrete example ?
    • samshers
      samshers over 6 years
      i have seen it on my project code. I don't know much about opensource projects... so can't point to any effectively. My thinking is @Component annotation on interfaces adds no value. So any such annotations I saw might be just unnecessary. Just was interested in discussing the same on SoF. And your explicit question makes me think that such annotations on interfaces are not required? Right?
    • samshers
      samshers over 6 years
      ... but if compiler could throw an error or atleast a warning to such annotations as they add no value, it would have been more clear? And as no such thing is done by compiler, i though i should double check to see I am not missing any thing important.
    • davidxxx
      davidxxx over 6 years
      @samshers It "works" but it is not a good practice. So, in a some way, yes annotating the interface is not required. I did a answer.
  • anche
    anche over 2 years
    @samshers, why is this not marked as the accepted answer?