Не удается получить @Component для наследования в Spring?

В моем проекте есть общий базовый класс, который распространяется на все классы клиентов. Это поле @Autowired, которое должно быть введено Hibernate. Все они группируются в другом классе, который имеет @Autowired коллекцию базового класса.

Чтобы уменьшить шаблон для клиентского кода, я пытаюсь получить @Component в наследство. Если @Component не делает этого по умолчанию (видимо он использовал, хотя), я создал эту обходную аннотацию

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

... и аннотировал базовый класс с ним. Это не очень, но я надеялся, что это сработает. К сожалению, этого не произошло, что меня действительно смущает, поскольку @Inherited должен заставить его работать

Есть ли другой способ получить @Component в наследство? Или я просто должен сказать, что любой класс, который расширяет базовый класс, нуждается в этом шаблоне?

Ответ 1

Проблема заключается в том, что сам тип аннотации Component должен быть помечен @Inherited.

Тип аннотации @InheritedComponent правильно унаследован любыми классами, которые расширяют суперкласс, который помечен @InheritedComponent - но он не наследует @Component. Это связано с тем, что у вас есть @Component для аннотации, а не для родительского типа.

Пример:

public class InheritedAnnotationTest {

    @InheritedComponent
    public static class BaseComponent {
    }

    public static class SubClass extends BaseComponent {
    }

    public static void main(String[] args) {
        SubClass s = new SubClass();

        for (Annotation a : s.getClass().getAnnotations()) {
            System.out.printf("%s has annotation %s\n", s.getClass(), a);
        }
    }
}

Вывод:

класс brown.annotations.InheritedAnnotationTest $SubClass имеет аннотацию @brown.annotations.InheritedComponent()

Другими словами, при разрешении тех аннотаций, которые имеет класс, аннотации аннотаций не разрешаются - они не применяются к классу, а только аннотация (если это имеет смысл).

Ответ 2

Я справился с этой проблемой, создав собственную аннотацию (наследуя), а затем настроил сканирование классов:

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

Spring Конфигурация выглядит так:

<context:component-scan base-package="io.bar">
        <context:include-filter type="annotation"
            expression="io.bar.core.annotations.BusinessService" />
    </context:component-scan>

from Spring doc 5.10.3 Использование фильтров для настройки сканирования