Spring IoC контейнер: сканирование classpath, использование метааннотаций и составных аннотаций

Многие из аннотаций, предоставляемых Spring, могут использоваться как метааннотации в вашем собственном коде. Метааннотация - это аннотация, которая может быть применена к другой аннотации. Например, упомянутая ранее аннотация @Service мета-аннотирована с помощью @Component, как показано в следующем примере:

Java

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component // Component заставляет @Service обрабатываться так же, как @Component.
public @interface Service {

    // ...
}

Kotlin

@Target(AnnotationTarget.TYPE)
@Retention(AnnotationRetention.RUNTIME)
@MustBeDocumented
@Component // Component заставляет @Service обрабатываться так же, как @Component.
annotation class Service {

    // ...
}

Вы также можете комбинировать метааннотации для создания "составных аннотаций". Например, аннотация @RestController из Spring MVC состоит из @Controller и @ResponseBody.

Кроме того, составные аннотации могут по желанию повторно объявлять атрибуты из метааннотаций для обеспечения возможности настройки. Это может быть особенно полезно, когда вы хотите предоставить только подмножество атрибутов метааннотации. Например, аннотация Spring @SessionScope жестко кодирует имя области для сеанса (session), но все же позволяет настраивать proxyMode. В следующем листинге показано определение аннотации SessionScope:

Java

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Scope(WebApplicationContext.SCOPE_SESSION)
public @interface SessionScope {

    /**
     * Псевдоним для {@link Scope#proxyMode}.
     * По умолчанию используется {@link ScopedProxyMode#TARGET_CLASS}.
     */
    @AliasFor(annotation = Scope.class)
    ScopedProxyMode proxyMode() default ScopedProxyMode.TARGET_CLASS;

}

Kotlin

@Target(AnnotationTarget.TYPE, AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
@MustBeDocumented
@Scope(WebApplicationContext.SCOPE_SESSION)
annotation class SessionScope(
        @get:AliasFor(annotation = Scope::class)
        val proxyMode: ScopedProxyMode = ScopedProxyMode.TARGET_CLASS
)

Затем вы можете использовать @SessionScope без объявления proxyMode следующим образом:

Java

@Service
@SessionScope
public class SessionScopedService {
    // ...
}

Kotlin

@Service
@SessionScope
class SessionScopedService {
    // ...
}

Вы также можете переопределить значение для proxyMode, как показано в следующем примере:

Java

@Service
@SessionScope(proxyMode = ScopedProxyMode.INTERFACES)
public class SessionScopedUserService implements UserService {
    // ...
}

Kotlin

@Service
@SessionScope(proxyMode = ScopedProxyMode.INTERFACES)
class SessionScopedUserService : UserService {
    // ...
}


Читайте также:


Комментарии

Популярные сообщения из этого блога

Методы класса Object в Java

Как получить текущий timestamp в Java

Основные опции JVM для повышения производительности и отладки