1. Обзор
В этом руководстве мы обсудим наиболее распространенные аннотации компонентов Spring , используемые для определения различных типов компонентов.
Есть несколько способов настроить bean-компоненты в контейнере Spring. Во-первых, мы можем объявить их с помощью конфигурации XML. Мы также можем объявить bean-компоненты, используя аннотацию @Bean
в классе конфигурации.
Наконец, мы можем пометить класс одной из аннотаций из пакета org.springframework.stereotype
, а остальные оставить для сканирования компонентов.
2. Сканирование компонентов
Spring может автоматически сканировать пакет на наличие bean-компонентов, если включено сканирование компонентов.
@ComponentScan
настраивает, какие пакеты сканировать на наличие классов с конфигурацией аннотаций . Мы можем указать имена базовых пакетов напрямую с одним из аргументов basePackages
или value
( value
— это псевдоним для basePackages
):
@Configuration
@ComponentScan(basePackages = "com.foreach.annotations")
class VehicleFactoryConfig {}
Также мы можем указать классы в базовых пакетах с помощью аргумента basePackageClasses
:
@Configuration
@ComponentScan(basePackageClasses = VehicleFactoryConfig.class)
class VehicleFactoryConfig {}
Оба аргумента являются массивами, так что мы можем предоставить несколько пакетов для каждого.
Если аргумент не указан, сканирование происходит из того же пакета, в котором присутствует аннотированный класс @ComponentScan .
@ComponentScan
использует функцию повторяющихся аннотаций Java 8, что означает, что мы можем помечать ею класс несколько раз:
@Configuration
@ComponentScan(basePackages = "com.foreach.annotations")
@ComponentScan(basePackageClasses = VehicleFactoryConfig.class)
class VehicleFactoryConfig {}
В качестве альтернативы мы можем использовать @ComponentScans
для указания нескольких конфигураций @ComponentScan
:
@Configuration
@ComponentScans({
@ComponentScan(basePackages = "com.foreach.annotations"),
@ComponentScan(basePackageClasses = VehicleFactoryConfig.class)
})
class VehicleFactoryConfig {}
При использовании конфигурации XML настроить сканирование компонентов так же просто:
<context:component-scan base-package="com.foreach" />
3. @Компонент
@Component
— это аннотация уровня класса. Во время сканирования компонентов Spring Framework автоматически обнаруживает классы, аннотированные @Component:
@Component
class CarUtility {
// ...
}
По умолчанию экземпляры bean-компонентов этого класса имеют то же имя, что и имя класса, с начальной строчной буквой. Кроме того, мы можем указать другое имя, используя необязательный аргумент значения этой аннотации.
Поскольку @Repository
, @Service
, @Configuration
и @Controller
являются мета-аннотациями @Component
, они имеют одинаковое поведение при именовании компонентов. Spring также автоматически подбирает их в процессе сканирования компонентов.
4. @Репозиторий
Классы 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
public class VehicleService {
// ...
}
6. @Контроллер
@Controller
— это аннотация уровня класса, которая сообщает Spring Framework, что этот класс служит контроллером в Spring MVC :
@Controller
public class VehicleController {
// ...
}
7. @Конфигурация
`Классы
конфигурации могут**содержать методы определения компонентов,** аннотированные с помощью
@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 .