diff --git a/spring-aspects/src/main/java/org/springframework/transaction/aspectj/AbstractTransactionAspect.aj b/spring-aspects/src/main/java/org/springframework/transaction/aspectj/AbstractTransactionAspect.aj deleted file mode 100644 index 782ca35e0777..000000000000 --- a/spring-aspects/src/main/java/org/springframework/transaction/aspectj/AbstractTransactionAspect.aj +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2002-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.transaction.aspectj; - -import org.aspectj.lang.annotation.SuppressAjWarnings; -import org.aspectj.lang.reflect.MethodSignature; - -import org.springframework.beans.factory.DisposableBean; -import org.springframework.transaction.interceptor.TransactionAspectSupport; -import org.springframework.transaction.interceptor.TransactionAttributeSource; - -/** - * Abstract superaspect for AspectJ transaction aspects. Concrete - * subaspects will implement the {@code transactionalMethodExecution()} - * pointcut using a strategy such as Java 5 annotations. - * - *
Suitable for use inside or outside the Spring IoC container. - * Set the "transactionManager" property appropriately, allowing - * use of any transaction implementation supported by Spring. - * - *
NB: If a method implements an interface that is itself
- * transactionally annotated, the relevant Spring transaction attribute
- * will not be resolved. This behavior will vary from that of Spring AOP
- * if proxying an interface (but not when proxying a class). We recommend that
- * transaction annotations should be added to classes, rather than business
- * interfaces, as they are an implementation detail rather than a contract
- * specification validation.
- *
- * @author Rod Johnson
- * @author Ramnivas Laddad
- * @author Juergen Hoeller
- * @since 2.0
- */
-public abstract aspect AbstractTransactionAspect extends TransactionAspectSupport implements DisposableBean {
-
- /**
- * Construct the aspect using the given transaction metadata retrieval strategy.
- * @param tas TransactionAttributeSource implementation, retrieving Spring
- * transaction metadata for each joinpoint. Implement the subclass to pass in
- * {@code null} if it is intended to be configured through Setter Injection.
- */
- protected AbstractTransactionAspect(TransactionAttributeSource tas) {
- setTransactionAttributeSource(tas);
- }
-
- @Override
- public void destroy() {
- // An aspect is basically a singleton -> cleanup on destruction
- clearTransactionManagerCache();
- }
-
- @SuppressAjWarnings("adviceDidNotMatch")
- Object around(final Object txObject): transactionalMethodExecution(txObject) {
- MethodSignature methodSignature = (MethodSignature) thisJoinPoint.getSignature();
- // Adapt to TransactionAspectSupport's invokeWithinTransaction...
- try {
- return invokeWithinTransaction(methodSignature.getMethod(), txObject.getClass(), new InvocationCallback() {
- public Object proceedWithInvocation() throws Throwable {
- return proceed(txObject);
- }
- });
- }
- catch (RuntimeException | Error ex) {
- throw ex;
- }
- catch (Throwable thr) {
- Rethrower.rethrow(thr);
- throw new IllegalStateException("Should never get here", thr);
- }
- }
-
- /**
- * Concrete subaspects must implement this pointcut, to identify
- * transactional methods. For each selected joinpoint, TransactionMetadata
- * will be retrieved using Spring's TransactionAttributeSource interface.
- */
- protected abstract pointcut transactionalMethodExecution(Object txObject);
-
-
- /**
- * Ugly but safe workaround: We need to be able to propagate checked exceptions,
- * despite AspectJ around advice supporting specifically declared exceptions only.
- */
- private static class Rethrower {
-
- public static void rethrow(final Throwable exception) {
- class CheckedExceptionRethrower When using this aspect, you must annotate the implementation class
- * (and/or methods within that class), not the interface (if any) that
- * the class implements. AspectJ follows Java's rule that annotations on
- * interfaces are not inherited.
- *
- * An @Transactional annotation on a class specifies the default transaction
- * semantics for the execution of any public operation in the class.
- *
- * An @Transactional annotation on a method within the class overrides the
- * default transaction semantics given by the class annotation (if present).
- * Any method may be annotated (regardless of visibility). Annotating
- * non-public methods directly is the only way to get transaction demarcation
- * for the execution of such operations.
- *
- * @author Rod Johnson
- * @author Ramnivas Laddad
- * @author Adrian Colyer
- * @since 2.0
- * @see org.springframework.transaction.annotation.Transactional
- */
-public aspect AnnotationTransactionAspect extends AbstractTransactionAspect {
-
- public AnnotationTransactionAspect() {
- super(new AnnotationTransactionAttributeSource(false));
- }
-
- /**
- * Matches the execution of any public method in a type with the Transactional
- * annotation, or any subtype of a type with the Transactional annotation.
- */
- private pointcut executionOfAnyPublicMethodInAtTransactionalType() :
- execution(public * ((@Transactional *)+).*(..)) && within(@Transactional *);
-
- /**
- * Matches the execution of any method with the Transactional annotation.
- */
- private pointcut executionOfTransactionalMethod() :
- execution(@Transactional * *(..));
-
- /**
- * Definition of pointcut from super aspect - matched join points
- * will have Spring transaction management applied.
- */
- protected pointcut transactionalMethodExecution(Object txObject) :
- (executionOfAnyPublicMethodInAtTransactionalType() || executionOfTransactionalMethod() ) && this(txObject);
-
-}
diff --git a/spring-aspects/src/main/java/org/springframework/transaction/aspectj/AnnotationTransactionAspect.java b/spring-aspects/src/main/java/org/springframework/transaction/aspectj/AnnotationTransactionAspect.java
new file mode 100644
index 000000000000..2a40fbe2583c
--- /dev/null
+++ b/spring-aspects/src/main/java/org/springframework/transaction/aspectj/AnnotationTransactionAspect.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2002-2025 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.transaction.aspectj;
+
+
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.annotation.RequiredTypes;
+import org.aspectj.lang.annotation.SuppressAjWarnings;
+import org.aspectj.lang.reflect.MethodSignature;
+
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.transaction.annotation.AnnotationTransactionAttributeSource;
+import org.springframework.transaction.interceptor.TransactionAspectSupport;
+
+/**
+ * Concrete AspectJ transaction aspect using Spring's
+ * {@link org.springframework.transaction.annotation.Transactional} annotation.
+ *
+ * When using this aspect, you must annotate the implementation class
+ * (and/or methods within that class), not the interface (if any) that
+ * the class implements. AspectJ follows Java's rule that annotations on
+ * interfaces are not inherited.
+ *
+ * An @Transactional annotation on a class specifies the default transaction
+ * semantics for the execution of any public operation in the class.
+ *
+ * An @Transactional annotation on a method within the class overrides the
+ * default transaction semantics given by the class annotation (if present).
+ * Any method may be annotated (regardless of visibility). Annotating
+ * non-public methods directly is the only way to get transaction demarcation
+ * for the execution of such operations.
+ *
+ * @author Rod Johnson
+ * @author Ramnivas Laddad
+ * @author Adrian Colyer
+ * @author Joshua Chen
+ * @since 2.0
+ * @see org.springframework.transaction.annotation.Transactional
+ */
+@Aspect
+@RequiredTypes("org.springframework.transaction.annotation.Transactional")
+public class AnnotationTransactionAspect extends TransactionAspectSupport implements DisposableBean {
+
+ /**
+ * Construct the aspect using the default transaction metadata retrieval strategy.
+ */
+ public AnnotationTransactionAspect() {
+ new AnnotationTransactionAttributeSource(false); // Use AnnotationTransactionAttributeSource
+ }
+
+ @Override
+ public void destroy() {
+ // An aspect is basically a singleton -> cleanup on destruction
+ clearTransactionManagerCache();
+ }
+
+ /**
+ * Around advice: Intercepts transactional method execution.
+ * @param joinPoint proceedingJoinPoint context for the joinpoint
+ * @param txObject the object passed to the joinpoint, defined by the subclass
+ * @return the result of the target method execution
+ * @throws Throwable exceptions are rethrown via the Rethrower class
+ */
+ @SuppressAjWarnings("adviceDidNotMatch")
+ @Around(value = "transactionalMethodExecution(txObject)", argNames = "joinPoint,txObject")
+ public Object around(final ProceedingJoinPoint joinPoint, final Object txObject) throws Throwable {
+ MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); try {
+ // Proceed with the method execution
+ return invokeWithinTransaction(methodSignature.getMethod(), txObject.getClass(), joinPoint::proceed);
+ }
+ catch (RuntimeException | Error ex) {
+ throw ex; // Rethrow runtime exceptions or errors
+ }
+ catch (Throwable thr) {
+ Rethrower.rethrow(thr); // Rethrow checked exceptions as runtime exceptions
+ throw new IllegalStateException("Should never get here", thr);
+ }
+ }
+
+ /**
+ * Matches the execution of any public method in a type with the Transactional
+ * annotation, or any subtype of a type with the Transactional annotation.
+ */
+ @Pointcut("execution(public * ((@org.springframework.transaction.annotation.Transactional *)+).*(..)) && within(@org.springframework.transaction.annotation.Transactional *)")
+ private void executionOfAnyPublicMethodInAtTransactionalType() {
+ }
+
+ /**
+ * Matches the execution of any method with the Transactional annotation.
+ */
+ @Pointcut("execution(@org.springframework.transaction.annotation.Transactional * *(..))")
+ private void executionOfTransactionalMethod() {
+ }
+
+ /**
+ * Definition of pointcut from super aspect - matched join points
+ * will have Spring transaction management applied.
+ */
+ @Pointcut(value = "(executionOfAnyPublicMethodInAtTransactionalType() || executionOfTransactionalMethod()) && this(txObject)", argNames = "txObject")
+ public void transactionalMethodExecution(Object txObject) {
+ }
+
+ /**
+ * Helper class to rethrow checked exceptions as runtime exceptions (workaround
+ * for AspectJ's restriction on checked exceptions in around advice).
+ */
+ private static class Rethrower {
+ public static void rethrow(final Throwable exception) {
+ class CheckedExceptionRethrower When using this aspect, you must annotate the implementation class
- * (and/or methods within that class), not the interface (if any) that
- * the class implements. AspectJ follows Java's rule that annotations on
- * interfaces are not inherited.
- *
- * An @Transactional annotation on a class specifies the default transaction
- * semantics for the execution of any public operation in the class.
- *
- * An @Transactional annotation on a method within the class overrides the
- * default transaction semantics given by the class annotation (if present).
- * Any method may be annotated (regardless of visibility). Annotating
- * non-public methods directly is the only way to get transaction demarcation
- * for the execution of such operations.
- *
- * @author Stephane Nicoll
- * @since 4.2
- * @see jakarta.transaction.Transactional
- * @see AnnotationTransactionAspect
- */
-@RequiredTypes("jakarta.transaction.Transactional")
-public aspect JtaAnnotationTransactionAspect extends AbstractTransactionAspect {
-
- public JtaAnnotationTransactionAspect() {
- super(new AnnotationTransactionAttributeSource(false));
- }
-
- /**
- * Matches the execution of any public method in a type with the Transactional
- * annotation, or any subtype of a type with the Transactional annotation.
- */
- private pointcut executionOfAnyPublicMethodInAtTransactionalType() :
- execution(public * ((@Transactional *)+).*(..)) && within(@Transactional *);
-
- /**
- * Matches the execution of any method with the Transactional annotation.
- */
- private pointcut executionOfTransactionalMethod() :
- execution(@Transactional * *(..));
-
- /**
- * Definition of pointcut from super aspect - matched join points
- * will have Spring transaction management applied.
- */
- protected pointcut transactionalMethodExecution(Object txObject) :
- (executionOfAnyPublicMethodInAtTransactionalType() || executionOfTransactionalMethod() ) && this(txObject);
-
-}
diff --git a/spring-aspects/src/main/java/org/springframework/transaction/aspectj/JtaAnnotationTransactionAspect.java b/spring-aspects/src/main/java/org/springframework/transaction/aspectj/JtaAnnotationTransactionAspect.java
new file mode 100644
index 000000000000..c695e1fca847
--- /dev/null
+++ b/spring-aspects/src/main/java/org/springframework/transaction/aspectj/JtaAnnotationTransactionAspect.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2002-2025 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.transaction.aspectj;
+
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.annotation.RequiredTypes;
+import org.aspectj.lang.annotation.SuppressAjWarnings;
+import org.aspectj.lang.reflect.MethodSignature;
+
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.transaction.annotation.AnnotationTransactionAttributeSource;
+import org.springframework.transaction.interceptor.TransactionAspectSupport;
+
+/**
+ * Concrete AspectJ transaction aspect using the JTA 1.2
+ * {@link jakarta.transaction.Transactional} annotation.
+ *
+ * When using this aspect, you must annotate the implementation class
+ * (and/or methods within that class), not the interface (if any) that
+ * the class implements. AspectJ follows Java's rule that annotations on
+ * interfaces are not inherited.
+ *
+ * An @Transactional annotation on a class specifies the default transaction
+ * semantics for the execution of any public operation in the class.
+ *
+ * An @Transactional annotation on a method within the class overrides the
+ * default transaction semantics given by the class annotation (if present).
+ * Any method may be annotated (regardless of visibility). Annotating
+ * non-public methods directly is the only way to get transaction demarcation
+ * for the execution of such operations.
+ *
+ * @author Stephane Nicoll
+ * @author Joshua Chen
+ * @since 4.2
+ * @see jakarta.transaction.Transactional
+ * @see AnnotationTransactionAspect
+ */
+@Aspect
+@RequiredTypes("jakarta.transaction.Transactional")
+public class JtaAnnotationTransactionAspect extends TransactionAspectSupport implements DisposableBean {
+
+ /**
+ * Construct the aspect using the default transaction metadata retrieval strategy.
+ */
+ public JtaAnnotationTransactionAspect() {
+ new AnnotationTransactionAttributeSource(false); // Use AnnotationTransactionAttributeSource
+ }
+
+ @Override
+ public void destroy() {
+ // An aspect is basically a singleton -> cleanup on destruction
+ clearTransactionManagerCache();
+ }
+
+ /**
+ * Around advice: intercepts transactional method execution.
+ * @param joinPoint proceedingJoinPoint context for the joinpoint
+ * @param txObject the object passed to the joinpoint, defined by the subclass
+ * @return the result of the target method execution
+ * @throws Throwable exceptions are rethrown via the Rethrower class
+ */
+ @SuppressAjWarnings("adviceDidNotMatch")
+ @Around(value = "transactionalMethodExecution(txObject)", argNames = "joinPoint,txObject")
+ public Object around(final ProceedingJoinPoint joinPoint, final Object txObject) throws Throwable {
+ MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); try {
+ // Proceed with the method execution
+ return invokeWithinTransaction(methodSignature.getMethod(), txObject.getClass(), joinPoint::proceed);
+ }
+ catch (RuntimeException | Error ex) {
+ throw ex; // Rethrow runtime exceptions or errors
+ }
+ catch (Throwable thr) {
+ JtaAnnotationTransactionAspect.Rethrower.rethrow(thr); // Rethrow checked exceptions as runtime exceptions
+ throw new IllegalStateException("Should never get here", thr);
+ }
+ }
+
+ /**
+ * Matches the execution of any public method in a type with the Transactional
+ * annotation, or any subtype of a type with the Transactional annotation.
+ */
+ @Pointcut("execution(public * ((@jakarta.transaction.Transactional *)+).*(..)) && within(@jakarta.transaction.Transactional *)")
+ private void executionOfAnyPublicMethodInAtTransactionalType() {
+ }
+
+ /**
+ * Matches the execution of any method with the Transactional annotation.
+ */
+ @Pointcut("execution(@jakarta.transaction.Transactional * *(..))")
+ private void executionOfTransactionalMethod() {
+ }
+
+ /**
+ * Definition of pointcut from super aspect - matched join points
+ * will have Spring transaction management applied.
+ */
+ @Pointcut(value = "(executionOfAnyPublicMethodInAtTransactionalType() || executionOfTransactionalMethod()) && this(txObject)", argNames = "txObject")
+ public void transactionalMethodExecution(Object txObject) {
+ }
+
+ /**
+ * Helper class to rethrow checked exceptions as runtime exceptions (workaround
+ * for AspectJ's restriction on checked exceptions in around advice).
+ */
+ private static class Rethrower {
+ public static void rethrow(final Throwable exception) {
+ class CheckedExceptionRethrower