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
|
@MyServicepublic 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
|
@ApiKeyprivate 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
|
@MockMvcTestpublic 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, являются их собственными. |