Skip to content

Upgrade AspectJ Transaction to 5 to Fix Proxy Issue #34656

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -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.
*
* <p>When using this aspect, you <i>must</i> annotate the implementation class
* (and/or methods within that class), <i>not</i> the interface (if any) that
* the class implements. AspectJ follows Java's rule that annotations on
* interfaces are <i>not</i> inherited.
*
* <p>An @Transactional annotation on a class specifies the default transaction
* semantics for the execution of any <b>public</b> operation in the class.
*
* <p>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<T extends Throwable> {
@SuppressWarnings("unchecked")
private void rethrow(Throwable exception) throws T {
throw (T) exception; // Rethrow the exception as unchecked
}
} new CheckedExceptionRethrower<RuntimeException>().rethrow(exception);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* 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.
Expand Down Expand Up @@ -43,12 +43,11 @@ public class AspectJJtaTransactionManagementConfiguration extends AspectJTransac
@Bean(name = TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public JtaAnnotationTransactionAspect jtaTransactionAspect(TransactionAttributeSource transactionAttributeSource) {
JtaAnnotationTransactionAspect txAspect = JtaAnnotationTransactionAspect.aspectOf();
JtaAnnotationTransactionAspect txAspect = new JtaAnnotationTransactionAspect();
txAspect.setTransactionAttributeSource(transactionAttributeSource);
if (this.txManager != null) {
txAspect.setTransactionManager(this.txManager);
}
return txAspect;
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* 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.
Expand Down Expand Up @@ -45,12 +45,11 @@ public class AspectJTransactionManagementConfiguration extends AbstractTransacti
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ASPECT_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public AnnotationTransactionAspect transactionAspect(TransactionAttributeSource transactionAttributeSource) {
AnnotationTransactionAspect txAspect = AnnotationTransactionAspect.aspectOf();
AnnotationTransactionAspect txAspect = new AnnotationTransactionAspect();
txAspect.setTransactionAttributeSource(transactionAttributeSource);
if (this.txManager != null) {
txAspect.setTransactionManager(this.txManager);
}
return txAspect;
}

}
Loading