«1. Обзор

В этой статье мы обсудим наиболее распространенные аннотации компонентов Spring, используемые для определения различных типов компонентов.

Есть несколько способов настроить bean-компоненты в контейнере Spring. Мы можем объявить их с помощью конфигурации XML. Мы можем объявить bean-компоненты, используя аннотацию @Bean в классе конфигурации.

Или мы можем пометить класс одной из аннотаций из пакета org.springframework.stereotype, а остальные оставить для сканирования компонентов.

2. Сканирование компонентов

Spring может автоматически сканировать пакет на наличие bean-компонентов, если включено сканирование компонентов.

@ComponentScan определяет, какие пакеты сканировать на наличие классов с конфигурацией аннотаций. Мы можем указать имена базовых пакетов напрямую с одним из аргументов basePackages или value (значение является псевдонимом для basePackages):

@Configuration
@ComponentScan(basePackages = "com.baeldung.annotations")
class VehicleFactoryConfig {}

Также мы можем указывать на классы в базовых пакетах с помощью аргумента basePackageClasses:

@Configuration
@ComponentScan(basePackageClasses = VehicleFactoryConfig.class)
class VehicleFactoryConfig {}

Оба аргумента являются массивами, так что мы можем предоставить несколько пакетов для каждого.

Если аргумент не указан, сканирование происходит из того же пакета, в котором присутствует аннотированный класс @ComponentScan.

@ComponentScan использует функцию повторяющихся аннотаций Java 8, что означает, что мы можем помечать ею класс несколько раз:

@Configuration
@ComponentScan(basePackages = "com.baeldung.annotations")
@ComponentScan(basePackageClasses = VehicleFactoryConfig.class)
class VehicleFactoryConfig {}

Кроме того, мы можем использовать @ComponentScans для указания нескольких конфигураций @ComponentScan:

@Configuration
@ComponentScans({ 
  @ComponentScan(basePackages = "com.baeldung.annotations"), 
  @ComponentScan(basePackageClasses = VehicleFactoryConfig.class)
})
class VehicleFactoryConfig {}

~~ ~ При использовании конфигурации XML настройка сканирования компонентов выполняется так же просто:

<context:component-scan base-package="com.baeldung" />

3. @Component

@Component — это аннотация уровня класса. Во время сканирования компонентов Spring Framework автоматически обнаруживает классы, аннотированные с помощью @Component.

Например:

@Component
class CarUtility {
    // ...
}

По умолчанию экземпляры bean-компонентов этого класса имеют то же имя, что и имя класса, с начальной строчной буквой. Кроме того, мы можем указать другое имя, используя необязательный аргумент значения этой аннотации.

Поскольку @Repository, @Service, @Configuration и @Controller являются мета-аннотациями @Component, они имеют одинаковое поведение при именовании компонентов. Кроме того, Spring автоматически подбирает их в процессе сканирования компонентов.

4. @Repository

Классы DAO или Repository обычно представляют уровень доступа к базе данных в приложении и должны быть аннотированы с помощью @Repository:

@Repository
class VehicleRepository {
    // ...
}

Одним из преимуществ использования этой аннотации является ее автоматическое сохранение. перевод исключений включен. При использовании среды сохраняемости, такой как Hibernate, собственные исключения, созданные в классах, аннотированных с помощью @Repository, будут автоматически преобразованы в подклассы Spring DataAccessExeption.

Чтобы включить преобразование исключений, нам нужно объявить собственный bean-компонент PersistenceExceptionTranslationPostProcessor:

@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
    return new PersistenceExceptionTranslationPostProcessor();
}

Обратите внимание, что в большинстве случаев Spring выполняет описанный выше шаг автоматически.

Или с помощью конфигурации XML:

<bean class=
  "org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>

5. @Service

Бизнес-логика приложения обычно находится на уровне сервиса, поэтому мы будем использовать аннотацию @Service, чтобы указать, что class принадлежит этому слою:

@Service
public class VehicleService {
    // ...    
}

6. @Controller

@Controller — это аннотация уровня класса, которая сообщает Spring Framework, что этот класс служит контроллером в Spring MVC:

@Controller
public class VehicleController {
    // ...
}

7. @Configuration

Классы конфигурации могут содержать методы определения bean-компонентов, аннотированные с помощью @Bean:

@Configuration
class VehicleFactoryConfig {

    @Bean
    Engine engine() {
        return new Engine();
    }

}

8. Стереотипные аннотации и АОП

Когда мы используем стереотипные аннотации Spring, легко создать pointcut, предназначенный для всех классов, которые иметь определенный стереотип.

Например, предположим, что мы хотим измерить время выполнения методов из уровня DAO. Мы создадим следующий аспект (используя аннотации AspectJ), воспользовавшись стереотипом @Repository:

@Aspect
@Component
public class PerformanceAspect {
    @Pointcut("within(@org.springframework.stereotype.Repository *)")
    public void repositoryClassMethods() {};

    @Around("repositoryClassMethods()")
    public Object measureMethodExecutionTime(ProceedingJoinPoint joinPoint) 
      throws Throwable {
        long start = System.nanoTime();
        Object returnValue = joinPoint.proceed();
        long end = System.nanoTime();
        String methodName = joinPoint.getSignature().getName();
        System.out.println(
          "Execution of " + methodName + " took " + 
          TimeUnit.NANOSECONDS.toMillis(end - start) + " ms");
        return returnValue;
    }
}

В этом примере мы создали pointcut, который соответствует всем методам в классах, аннотированных @Repository. Мы использовали совет @Around, чтобы затем нацелиться на этот pointcut и определить время выполнения перехваченных вызовов методов.

Используя этот подход, мы можем добавить ведение журнала, управление производительностью, аудит или другие функции для каждого уровня приложения.

9. Заключение

«В этой статье мы рассмотрели аннотации стереотипов Spring и узнали, какой тип семантики они представляют.

Мы также узнали, как использовать сканирование компонентов, чтобы сообщить контейнеру, где найти аннотированные классы.

Наконец, мы увидели, как эти аннотации приводят к четкому, многоуровневому дизайну и разделению задач приложения. Они также делают конфигурацию меньше, так как нам больше не нужно явно определять bean-компоненты вручную.

Как обычно, примеры доступны на GitHub.

« Previous

Spring Data Annotations