From 5b24040b5e1dc2ba90aacd656403c3b5f90d8aee Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Fri, 29 Jun 2018 19:43:38 +0200 Subject: [PATCH] JtaAnnotationTransactionAspect configured by default (in aspectj mode) Issue: SPR-16987 --- ...JtaTransactionManagementConfiguration.java | 51 +++++++++++++++++++ ...ctJTransactionManagementConfiguration.java | 7 ++- .../aspectj/JtaAnnotationTransactionAspect.aj | 2 +- ...actionManagementConfigurationSelector.java | 13 ++++- .../AnnotationDrivenBeanDefinitionParser.java | 18 ++++++- .../TransactionManagementConfigUtils.java | 23 ++++++++- .../EnableTransactionManagementTests.java | 4 +- ...TransactionManagementIntegrationTests.java | 15 +++--- 8 files changed, 115 insertions(+), 18 deletions(-) create mode 100644 spring-aspects/src/main/java/org/springframework/transaction/aspectj/AspectJJtaTransactionManagementConfiguration.java diff --git a/spring-aspects/src/main/java/org/springframework/transaction/aspectj/AspectJJtaTransactionManagementConfiguration.java b/spring-aspects/src/main/java/org/springframework/transaction/aspectj/AspectJJtaTransactionManagementConfiguration.java new file mode 100644 index 0000000000..fb644851f1 --- /dev/null +++ b/spring-aspects/src/main/java/org/springframework/transaction/aspectj/AspectJJtaTransactionManagementConfiguration.java @@ -0,0 +1,51 @@ +/* + * Copyright 2002-2018 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 + * + * http://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.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Role; +import org.springframework.transaction.annotation.EnableTransactionManagement; +import org.springframework.transaction.annotation.TransactionManagementConfigurationSelector; +import org.springframework.transaction.config.TransactionManagementConfigUtils; + +/** + * {@code @Configuration} class that registers the Spring infrastructure beans necessary + * to enable AspectJ-based annotation-driven transaction management for the JTA 1.2 + * {@link javax.transaction.Transactional} annotation in addition to Spring's own + * {@link org.springframework.transaction.annotation.Transactional} annotation. + * + * @author Juergen Hoeller + * @since 5.1 + * @see EnableTransactionManagement + * @see TransactionManagementConfigurationSelector + */ +@Configuration +public class AspectJJtaTransactionManagementConfiguration extends AspectJTransactionManagementConfiguration { + + @Bean(name = TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_BEAN_NAME) + @Role(BeanDefinition.ROLE_INFRASTRUCTURE) + public JtaAnnotationTransactionAspect jtaTransactionAspect() { + JtaAnnotationTransactionAspect txAspect = JtaAnnotationTransactionAspect.aspectOf(); + if (this.txManager != null) { + txAspect.setTransactionManager(this.txManager); + } + return txAspect; + } + +} diff --git a/spring-aspects/src/main/java/org/springframework/transaction/aspectj/AspectJTransactionManagementConfiguration.java b/spring-aspects/src/main/java/org/springframework/transaction/aspectj/AspectJTransactionManagementConfiguration.java index 41993f81d4..e0662bd6a8 100644 --- a/spring-aspects/src/main/java/org/springframework/transaction/aspectj/AspectJTransactionManagementConfiguration.java +++ b/spring-aspects/src/main/java/org/springframework/transaction/aspectj/AspectJTransactionManagementConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2018 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. @@ -27,12 +27,15 @@ import org.springframework.transaction.config.TransactionManagementConfigUtils; /** * {@code @Configuration} class that registers the Spring infrastructure beans necessary - * to enable AspectJ-based annotation-driven transaction management. + * to enable AspectJ-based annotation-driven transaction management for Spring's own + * {@link org.springframework.transaction.annotation.Transactional} annotation. * * @author Chris Beams + * @author Juergen Hoeller * @since 3.1 * @see EnableTransactionManagement * @see TransactionManagementConfigurationSelector + * @see AspectJJtaTransactionManagementConfiguration */ @Configuration public class AspectJTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration { diff --git a/spring-aspects/src/main/java/org/springframework/transaction/aspectj/JtaAnnotationTransactionAspect.aj b/spring-aspects/src/main/java/org/springframework/transaction/aspectj/JtaAnnotationTransactionAspect.aj index 6b02e1de3a..22a3bb134b 100644 --- a/spring-aspects/src/main/java/org/springframework/transaction/aspectj/JtaAnnotationTransactionAspect.aj +++ b/spring-aspects/src/main/java/org/springframework/transaction/aspectj/JtaAnnotationTransactionAspect.aj @@ -45,7 +45,7 @@ import org.springframework.transaction.annotation.AnnotationTransactionAttribute * @see javax.transaction.Transactional * @see AnnotationTransactionAspect */ -@RequiredTypes({"javax.transaction.Transactional"}) +@RequiredTypes("javax.transaction.Transactional") public aspect JtaAnnotationTransactionAspect extends AbstractTransactionAspect { public JtaAnnotationTransactionAspect() { diff --git a/spring-tx/src/main/java/org/springframework/transaction/annotation/TransactionManagementConfigurationSelector.java b/spring-tx/src/main/java/org/springframework/transaction/annotation/TransactionManagementConfigurationSelector.java index 145791f7a2..06598b96c0 100644 --- a/spring-tx/src/main/java/org/springframework/transaction/annotation/TransactionManagementConfigurationSelector.java +++ b/spring-tx/src/main/java/org/springframework/transaction/annotation/TransactionManagementConfigurationSelector.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2018 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. @@ -20,6 +20,7 @@ import org.springframework.context.annotation.AdviceMode; import org.springframework.context.annotation.AdviceModeImportSelector; import org.springframework.context.annotation.AutoProxyRegistrar; import org.springframework.transaction.config.TransactionManagementConfigUtils; +import org.springframework.util.ClassUtils; /** * Selects which implementation of {@link AbstractTransactionManagementConfiguration} @@ -27,10 +28,12 @@ import org.springframework.transaction.config.TransactionManagementConfigUtils; * importing {@code @Configuration} class. * * @author Chris Beams + * @author Juergen Hoeller * @since 3.1 * @see EnableTransactionManagement * @see ProxyTransactionManagementConfiguration * @see TransactionManagementConfigUtils#TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME + * @see TransactionManagementConfigUtils#JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME */ public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector { @@ -46,10 +49,16 @@ public class TransactionManagementConfigurationSelector extends AdviceModeImport case PROXY: return new String[] {AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()}; case ASPECTJ: - return new String[] {TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME}; + return new String[] {determineTransactionAspectClass()}; default: return null; } } + private String determineTransactionAspectClass() { + return (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader()) ? + TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME : + TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME); + } + } diff --git a/spring-tx/src/main/java/org/springframework/transaction/config/AnnotationDrivenBeanDefinitionParser.java b/spring-tx/src/main/java/org/springframework/transaction/config/AnnotationDrivenBeanDefinitionParser.java index eb827bf654..fa77828acc 100644 --- a/spring-tx/src/main/java/org/springframework/transaction/config/AnnotationDrivenBeanDefinitionParser.java +++ b/spring-tx/src/main/java/org/springframework/transaction/config/AnnotationDrivenBeanDefinitionParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2018 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. @@ -30,6 +30,7 @@ import org.springframework.lang.Nullable; import org.springframework.transaction.event.TransactionalEventListenerFactory; import org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor; import org.springframework.transaction.interceptor.TransactionInterceptor; +import org.springframework.util.ClassUtils; /** * {@link org.springframework.beans.factory.xml.BeanDefinitionParser @@ -64,6 +65,9 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser { if ("aspectj".equals(mode)) { // mode="aspectj" registerTransactionAspect(element, parserContext); + if (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader())) { + registerJtaTransactionAspect(element, parserContext); + } } else { // mode="proxy" @@ -84,6 +88,18 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser { } } + private void registerJtaTransactionAspect(Element element, ParserContext parserContext) { + String txAspectBeanName = TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_BEAN_NAME; + String txAspectClassName = TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CLASS_NAME; + if (!parserContext.getRegistry().containsBeanDefinition(txAspectBeanName)) { + RootBeanDefinition def = new RootBeanDefinition(); + def.setBeanClassName(txAspectClassName); + def.setFactoryMethodName("aspectOf"); + registerTransactionManager(element, def); + parserContext.registerBeanComponent(new BeanComponentDefinition(def, txAspectBeanName)); + } + } + private static void registerTransactionManager(Element element, BeanDefinition def) { def.getPropertyValues().add("transactionManagerBeanName", TxNamespaceHandler.getTransactionManagerName(element)); diff --git a/spring-tx/src/main/java/org/springframework/transaction/config/TransactionManagementConfigUtils.java b/spring-tx/src/main/java/org/springframework/transaction/config/TransactionManagementConfigUtils.java index 9b5f9fe8e7..36cbc2537d 100644 --- a/spring-tx/src/main/java/org/springframework/transaction/config/TransactionManagementConfigUtils.java +++ b/spring-tx/src/main/java/org/springframework/transaction/config/TransactionManagementConfigUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2018 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. @@ -49,6 +49,27 @@ public abstract class TransactionManagementConfigUtils { public static final String TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME = "org.springframework.transaction.aspectj.AspectJTransactionManagementConfiguration"; + /** + * The bean name of the internally managed JTA transaction aspect (used when mode == ASPECTJ). + * @since 5.1 + */ + public static final String JTA_TRANSACTION_ASPECT_BEAN_NAME = + "org.springframework.transaction.config.internalJtaTransactionAspect"; + + /** + * The class name of the AspectJ transaction management aspect. + * @since 5.1 + */ + public static final String JTA_TRANSACTION_ASPECT_CLASS_NAME = + "org.springframework.transaction.aspectj.JtaAnnotationTransactionAspect"; + + /** + * The name of the AspectJ transaction management @{@code Configuration} class for JTA. + * @since 5.1 + */ + public static final String JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME = + "org.springframework.transaction.aspectj.AspectJJtaTransactionManagementConfiguration"; + /** * The bean name of the internally managed TransactionalEventListenerFactory. */ diff --git a/spring-tx/src/test/java/org/springframework/transaction/annotation/EnableTransactionManagementTests.java b/spring-tx/src/test/java/org/springframework/transaction/annotation/EnableTransactionManagementTests.java index c49b112ff9..10d3659f33 100644 --- a/spring-tx/src/test/java/org/springframework/transaction/annotation/EnableTransactionManagementTests.java +++ b/spring-tx/src/test/java/org/springframework/transaction/annotation/EnableTransactionManagementTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2018 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. @@ -120,7 +120,7 @@ public class EnableTransactionManagementTests { "Do you actually have org.springframework.aspects on the classpath?"); } catch (Exception ex) { - assertThat(ex.getMessage(), containsString("AspectJTransactionManagementConfiguration")); + assertThat(ex.getMessage(), containsString("AspectJJtaTransactionManagementConfiguration")); } } diff --git a/src/test/java/org/springframework/transaction/annotation/EnableTransactionManagementIntegrationTests.java b/src/test/java/org/springframework/transaction/annotation/EnableTransactionManagementIntegrationTests.java index fde5359d9a..8dbe13d384 100644 --- a/src/test/java/org/springframework/transaction/annotation/EnableTransactionManagementIntegrationTests.java +++ b/src/test/java/org/springframework/transaction/annotation/EnableTransactionManagementIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2018 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. @@ -16,20 +16,14 @@ package org.springframework.transaction.annotation; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - import java.util.ArrayList; import java.util.Collections; import java.util.List; - import javax.sql.DataSource; import org.junit.Ignore; import org.junit.Test; + import org.springframework.aop.Advisor; import org.springframework.aop.framework.Advised; import org.springframework.aop.support.AopUtils; @@ -50,6 +44,9 @@ import org.springframework.tests.transaction.CallCountingTransactionManager; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor; +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; + /** * Integration tests for the @EnableTransactionManagement annotation. * @@ -122,7 +119,7 @@ public class EnableTransactionManagementIntegrationTests { // this test is a bit fragile, but gets the job done, proving that an // attempt was made to look up the AJ aspect. It's due to classpath issues // in .integration-tests that it's not found. - assertTrue(ex.getMessage().contains("AspectJTransactionManagementConfiguration")); + assertTrue(ex.getMessage().contains("AspectJJtaTransactionManagementConfiguration")); } }