Работает ли атрибут Spring @Transactional над частным методом?
Если у меня есть @Transactional -аннотация на частный метод в Spring bean, имеет ли аннотация какой-либо эффект?
Если @Transactional аннотация находится на общедоступном методе, он работает и открывает транзакцию.
public class Bean {
public void doStuff() {
doPrivateStuff();
}
@Transactional
private void doPrivateStuff() {
}
}
...
Bean bean = (Bean)appContext.getBean("bean");
bean.doStuff();
6 ответов:
ответа на ваш вопрос нет -
@Transactionalне будет иметь никакого эффекта, если используется для аннотирования частные методы. Генератор прокси будет игнорировать их.это задокументировано в руководство по пружинам глава 10.5.6:
видимость метода и
@Transactionalпри использовании прокси, вы должны применить элемент
@Transactionalаннотации только к методам с публичной видимостью. Если вы комментируете защищенные, частные или пакет-видимый методы с@Transactionalаннотация, без ошибок поднимается, но аннотированный метод не показывает настроенный транзакционные настройки. Рассмотрим использование AspectJ (см. ниже), Если вам нужно для аннотирования непубличных методов.
вопрос не является частным или публичным, вопрос в том, как он вызывается и какую реализацию AOP вы используете!
Если вы используете (по умолчанию) Spring Proxy AOP, то все функции AOP, предоставляемые Spring (например
@Transational) будет учитываться только в том случае, если вызов проходит через прокси. -- Обычно это происходит, если аннотированный метод вызывается из другое бобовые.это имеет два последствия:
- потому что частная методы не должны вызываться из другого компонента (исключение-отражение), их
@Transactionalаннотация не принимается во внимание.- если метод является общедоступным, но он вызывается из того же компонента, он также не будет учитываться (этот оператор корректен только в том случае, если (по умолчанию) используется прокси-сервер Spring AOP).
@See Весенняя ссылка: глава 9.6 9.6 проксирующие механизмы
IMHO вы должны использовать режим aspectJ, а не Весенние прокси, которые преодолеют проблему. А транзакционные аспекты AspectJ вплетены даже в частные методы (проверено на Spring 3.0).
по умолчанию
@Transactionalатрибут работает только при вызове аннотированного метода по ссылке, полученной из applicationContext.public class Bean { public void doStuff() { doTransactionStuff(); } @Transactional public void doTransactionStuff() { } }это откроет транзакцию:
Bean bean = (Bean)appContext.getBean("bean"); bean.doTransactionStuff();этого не будет:
Bean bean = (Bean)appContext.getBean("bean"); bean.doStuff();Spring Ссылка: С Помощью @Transactional
Примечание: в режиме прокси (который является по умолчанию), только "внешние" вызовы метода, поступающие через прокси будут перехвачены. Это означает, что 'self-invocation', т. е. метод в целевом объекте, вызывающий какой-либо другой метод целевого объекта, не приведет к фактической транзакции во время выполнения, даже если вызванный метод помечен
@Transactional!рассмотрите использование режима AspectJ (см. ниже), если вы ожидаете, что самопроизвольные вызовы также будут обернуты транзакциями. В этом случае в первую очередь не будет прокси; вместо этого целевой класс будет "сплетен" (т. е. его байтовый код будет изменен), чтобы повернуть
@TransactionalВ поведение во время выполнения какой-либо способ.
Да, можно использовать @Transactional на частных методах, но, как упоминали другие, это не будет работать из коробки. Вы должны использовать AspectJ. Мне потребовалось некоторое время, чтобы понять, как заставить его работать. Я поделюсь своими результатами.
я решил использовать ткачество во время компиляции вместо ткачества во время загрузки, потому что я думаю, что это в целом лучший вариант. Кроме того, я использую Java 8, поэтому вам может потребоваться настроить некоторые параметры.
во-первых, добавьте зависимость для aspectjrt.
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.8.8</version> </dependency>затем добавьте плагин AspectJ, чтобы выполнить фактическое переплетение байт-кода в Maven (это может быть не минимальный пример).
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>aspectj-maven-plugin</artifactId> <version>1.8</version> <configuration> <complianceLevel>1.8</complianceLevel> <source>1.8</source> <target>1.8</target> <aspectLibraries> <aspectLibrary> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> </aspectLibrary> </aspectLibraries> </configuration> <executions> <execution> <goals> <goal>compile</goal> </goals> </execution> </executions> </plugin>наконец добавьте это в свой класс конфигурации
@EnableTransactionManagement(mode = AdviceMode.ASPECTJ)Теперь вы должны быть в состоянии использовать @Transactional на частных методах.
одно предостережение к этому подходу: вам нужно будет настроить IDE, чтобы быть в курсе AspectJ в противном случае, если вы запустите приложение через Eclipse, например, он может не работать. Убедитесь, что вы тестируете против прямой сборки Maven в качестве проверки здравомыслия.
пожалуйста, смотрите этот документ:
в режиме прокси (по умолчанию) перехватываются только внешние вызовы методов, поступающие через прокси. Это означает, что самопроизвольный вызов метода в целевом объекте, вызывающего другой метод целевого объекта, не приведет к фактической транзакции во время выполнения, даже если вызванный метод помечен @Transactional.
рассмотрите использование режима AspectJ (см. атрибут mode в таблице ниже), если вы ожидаете собственной вызовы быть завернуты также в сделках. В этом случае в первую очередь не будет прокси; вместо этого целевой класс будет соткан (то есть его байтовый код будет изменен), чтобы превратить @Transactional в поведение среды выполнения для любого метода.
----------------------------за
Итак, пыльник - это пользователь BeanSelfAware
ответа нет. Пожалуйста, смотрите Весенняя Ссылка: Использование @Transactional :
на
@Transactionalаннотация может быть размещена перед определением интерфейса, методом на интерфейсе, определением класса или общественные метод на классе