Как расширить аннотацию Spring @Transactional

Мне нужно использовать 3 разных менеджера транзакций в моем веб-приложении. Поэтому я написал свою собственную аннотацию в соответствии с Ссылка на Spring (раздел 10.5.6.3 Пользовательские аннотации ярлыков).

Одна аннотация (для использования одного конкретного менеджера транзакций) выглядит так:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.transaction.annotation.Transactional;

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Transactional("customer")
public @interface CustomerTX{


}

Все работает нормально, когда я аннотирую мой сервисный слой с помощью настраиваемой аннотации @CustomerTX. Но я должен предоставить больше вариантов для моей аннотации, например readonly = true, rollbackFor = и так далее. Поскольку вы не можете «расширить» аннотацию (мне действительно просто нужно расширить аннотацию @Transactional из Spring), какова правильная реализация для этого?


person tim.kaufner    schedule 31.08.2010    source источник


Ответы (2)


Боюсь, вам придется создать несколько пользовательских аннотаций, по одной для каждого варианта использования, аннотируя каждую именно той аннотацией @Transactional, которая вам нужна.

Или вам придется написать свой собственный аспект в AspectJ (расширить org.springframework.transaction.aspectj.AbstractTransactionAspect из spring-sizes.jar), чтобы создать свою собственную логику транзакции.


Обновление: в то время это был правильный ответ, но начиная с Spring 4 и более поздних версий предпочтительнее ответ C.L.S

person Sean Patrick Floyd    schedule 31.08.2010
comment
Вы действительно имеете в виду, что я должен написать что-то вроде этого (при условии, что я просто хочу установить транзакцию только для чтения): @Target ({ElementType.METHOD, ElementType.TYPE}) @Retention (RetentionPolicy.RUNTIME) @Transactional (value = customer, readOnly = true) public @interface CustomerTXReadonly {} Это не может быть единственным рабочим решением ... - person tim.kaufner; 31.08.2010
comment
Боюсь, что да, из-за ограничений аннотаций. Как я уже сказал: либо это, либо написание ваших собственных аспектов (что я бы предпочел) - person Sean Patrick Floyd; 31.08.2010
comment
Спасибо за вашу помощь. Попробую написать свои аспекты. Жалко, что аннотации не расширяются :( - person tim.kaufner; 31.08.2010
comment
Возьмите копию AspectJ in Action: manning.com/laddad Это очень хорошая книга об AspectJ с Весна - person Sean Patrick Floyd; 31.08.2010
comment
Не могли бы вы уточнить, или вам придется написать свой собственный аспект в AspectJ (расширить org.springframework.transaction.aspectj.AbstractTransactionAspect из spring -Aspect.jar), чтобы создать свою собственную логику транзакции. Как это сделать? Спасибо - person Dikla; 18.08.2020
comment
@Dikla имейте в виду, что этому ответу 10 лет. с тех пор многое могло измениться, и, возможно, сейчас есть лучший подход. но в основном посмотрите на файлы .aj в этом каталоге: github.com/spring-projects/spring-framework/tree/master/. Посмотрите, как AnnotationTransactionAspect.aj расширяет AbstractTransactionAspect.aj и добавляет свой собственный подкласс, который делает то, что вам нужно. это довольно продвинутая штука, есть драконы. - person Sean Patrick Floyd; 19.08.2020
comment
Спасибо! Это было мое направление, я нашел эти классы путем отладки. Но как я могу сказать Spring использовать мой подкласс вместо обычных классов, которые он обычно использует? - person Dikla; 25.08.2020
comment
@Dikla, это, вероятно, ваша отправная точка: docs.spring.io/spring/docs/current/spring-framework-reference/ - person Sean Patrick Floyd; 11.09.2020
comment
Я там посмотрю. Большое спасибо! - person Dikla; 13.10.2020
comment
Обратите внимание, что другой ответ stackoverflow.com/a/49106255/3552141 - это правильный и простой способ, который использовался несколько лет назад. сейчас (с весны 4) - person jhyot; 26.03.2021
comment
@jhyot правда. добавил примечание к моему ответу - person Sean Patrick Floyd; 27.03.2021

Весной 4 года это можно сделать. Как указано в документация

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

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

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

    /**
     * Alias for {@link Scope#proxyMode}.
     * <p>Defaults to {@link ScopedProxyMode#TARGET_CLASS}.
     */
    @AliasFor(annotation = Scope.class)
    ScopedProxyMode proxyMode() default ScopedProxyMode.TARGET_CLASS;

}
person C.L.S    schedule 05.03.2018