Java Аннотации были введены с Java 5 еще в 2004 году как способ добавления метаданных в исходный код Java. Сегодня многие основные фреймворки, такие как Spring или Hibernate, сильно зависят от аннотаций.
В этой статье мы рассмотрим очень полезную функцию Spring, которая позволяет нам создавать собственные аннотации на основе одной или нескольких аннотаций Spring.
Составление пользовательской аннотации
Предположим, у нас есть набор аннотаций Spring, которые мы часто используем вместе. Типичным примером является комбинация @Service и @Transactional:
1
2
3
4
5
|
@Service @Transactional (rollbackFor = Exception. class , timeout = 5 ) public class UserService { ... } |
Вместо того, чтобы повторять обе аннотации снова и снова, мы можем создать нашу собственную аннотацию, содержащую эти две аннотации Spring. Создать нашу собственную аннотацию очень просто и выглядит так:
1
2
3
4
|
@Service @Transactional (rollbackFor = Exception. class , timeout = 5 ) @Retention (RetentionPolicy.RUNTIME) public @interface MyService {} |
Аннотация определяется с помощью ключевого слова @interface (вместо класса или интерфейса). Стандартная Java-аннотация @Retention используется для указания того, что аннотация должна обрабатываться во время выполнения. Мы также добавили обе аннотации Spring в нашу аннотацию.
Теперь мы можем использовать наши собственные аннотации @MyService для аннотации наших сервисов:
1
2
3
4
|
@MyService public class UserService { ... } |
Spring теперь обнаруживает, что @MyService аннотирован @Service и @Transactional и обеспечивает то же поведение, что и в предыдущем примере, причем обе аннотации присутствуют в классе UserService.
Обратите внимание, что это особенность способа обработки аннотаций Spring, а не общая функция Java. Аннотации других платформ и библиотек могут не работать, если вы добавите их в свою собственную аннотацию.
Примеры использования
Пользовательские аннотации могут использоваться в различных ситуациях для улучшения читаемости нашего кода. Вот два других примера, которые могут пригодиться.
Может быть, нам нужно значение свойства в разных местах нашего кода. Свойства часто вводятся с использованием аннотации Spring @Value:
1
2
3
|
// injects configuration properties my.api.key @Value ( "${my.api.key}" ) private String apiKey; |
В такой ситуации мы можем переместить выражение свойства из нашего кода в отдельную аннотацию:
1
2
3
|
@Value ( "${my.api.key}" ) @Retention (RetentionPolicy.RUNTIME) public @interface ApiKey {} |
В нашем коде теперь мы можем использовать @ApiKey вместо повтора выражения свойства везде:
1
2
|
@ApiKey private String apiKey; |
Другим примером являются интеграционные тесты. В тестах часто используются различные аннотации Spring для определения настроек теста. Эти аннотации могут быть сгруппированы с помощью пользовательской аннотации. Например, мы можем создать аннотацию @MockMvcTest, которая определяет настройку Spring для пробных тестов mvc:
1
2
3
4
5
6
|
@SpringBootTest @AutoConfigureMockMvc (secure = false ) @TestPropertySource (locations = "classpath:test.properties" ) @ExtendWith (SpringExtension. class ) @Retention (RetentionPolicy.RUNTIME) public @interface MockMvcTest {} |
Определение наших тестов теперь выглядит намного чище. Нам просто нужно добавить @MockMvcTest, чтобы получить полную настройку теста:
1
2
3
4
|
@MockMvcTest public class MyTest { ... } |
Обратите внимание, что наша аннотация @MockMvcTest также содержит аннотацию @ExtendWith JUnit 5. Как и Spring, JUnit 5 также может обнаруживать эту аннотацию, если она добавлена в вашу собственную пользовательскую аннотацию. Имейте в виду, что это не будет работать, если вы все еще используете JUnit 4. С JUnit 4 вы должны использовать @RunWith вместо @ExtendWith. К сожалению, @RunWith работает только тогда, когда размещается непосредственно в тестовом классе.
Примеры весной
Spring использует эту функцию в различных ситуациях для определения ярлыков для общих аннотаций.
Вот несколько примеров:
- @GetMapping — это короткая версия для @RequestMapping (method = {RequestMethod.GET}).
- @RestController — это сочетание @Controller и @ResponseBody.
- @SpringBootApplication — это ярлык для @SpringBootConfiguration, @EnableAutoConfiguration и @ComponentScan.
Вы можете убедиться в этом сами, посмотрев на определение этих аннотаций в исходном коде Spring.
Опубликовано на Java Code Geeks с разрешения Михаэля Шаргага, партнера нашей программы JCG. Смотрите оригинальную статью здесь: Составление пользовательских аннотаций с помощью Spring. Мнения, высказанные участниками Java Code Geeks, являются их собственными. |