mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-08-29 03:06:45 +08:00
Enable transaction management consistently
Previously to this commit, transaction management was only enabled when a `DataSource` is configured. The processing of `@Transactional` annotations are now enabled as long as a `PlatformTransactionManager` is present. Also, the `spring.aop.proxy-target-class` is now honoured if set, still defaulting to CGLIB mode. Closes gh-8434
This commit is contained in:
parent
751cd6e0b2
commit
db33a75484
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2016 the original author or authors.
|
||||
* Copyright 2012-2017 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.
|
||||
@ -32,8 +32,6 @@ import org.springframework.core.Ordered;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.annotation.AbstractTransactionManagementConfiguration;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for
|
||||
@ -79,11 +77,4 @@ public class DataSourceTransactionManagerAutoConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@ConditionalOnMissingBean(AbstractTransactionManagementConfiguration.class)
|
||||
@Configuration
|
||||
@EnableTransactionManagement(proxyTargetClass = true)
|
||||
protected static class TransactionManagementConfiguration {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2016 the original author or authors.
|
||||
* Copyright 2012-2017 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.
|
||||
@ -48,7 +48,6 @@ import org.springframework.jndi.JndiLocatorDelegate;
|
||||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||
import org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter;
|
||||
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
import org.springframework.transaction.jta.JtaTransactionManager;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
@ -61,8 +60,7 @@ import org.springframework.util.ClassUtils;
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass({ LocalContainerEntityManagerFactoryBean.class,
|
||||
EnableTransactionManagement.class, EntityManager.class })
|
||||
@ConditionalOnClass({ LocalContainerEntityManagerFactoryBean.class, EntityManager.class })
|
||||
@Conditional(HibernateEntityManagerCondition.class)
|
||||
@AutoConfigureAfter({ DataSourceAutoConfiguration.class })
|
||||
public class HibernateJpaAutoConfiguration extends JpaBaseConfiguration {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2016 the original author or authors.
|
||||
* Copyright 2012-2017 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,8 +20,10 @@ import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
|
||||
@ -30,6 +32,8 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.annotation.AbstractTransactionManagementConfiguration;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
/**
|
||||
@ -71,4 +75,25 @@ public class TransactionAutoConfiguration {
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnBean(PlatformTransactionManager.class)
|
||||
@ConditionalOnMissingBean(AbstractTransactionManagementConfiguration.class)
|
||||
public static class EnableTransactionManagementConfiguration {
|
||||
|
||||
@Configuration
|
||||
@EnableTransactionManagement(proxyTargetClass = false)
|
||||
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = false)
|
||||
public static class JdkDynamicAutoProxyConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableTransactionManagement(proxyTargetClass = true)
|
||||
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true)
|
||||
public static class CglibAutoProxyConfiguration {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2016 the original author or authors.
|
||||
* Copyright 2012-2017 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.
|
||||
@ -28,7 +28,6 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.annotation.AbstractTransactionManagementConfiguration;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
@ -52,8 +51,6 @@ public class DataSourceTransactionManagerAutoConfigurationTests {
|
||||
this.context.refresh();
|
||||
assertThat(this.context.getBean(DataSource.class)).isNotNull();
|
||||
assertThat(this.context.getBean(DataSourceTransactionManager.class)).isNotNull();
|
||||
assertThat(this.context.getBean(AbstractTransactionManagementConfiguration.class))
|
||||
.isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -68,8 +65,7 @@ public class DataSourceTransactionManagerAutoConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void testManualConfiguration() throws Exception {
|
||||
this.context.register(SwitchTransactionsOn.class,
|
||||
EmbeddedDataSourceConfiguration.class,
|
||||
this.context.register(EmbeddedDataSourceConfiguration.class,
|
||||
DataSourceTransactionManagerAutoConfiguration.class,
|
||||
TransactionAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
@ -79,8 +75,7 @@ public class DataSourceTransactionManagerAutoConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void testExistingTransactionManager() {
|
||||
this.context.register(SwitchTransactionsOn.class,
|
||||
TransactionManagerConfiguration.class,
|
||||
this.context.register(TransactionManagerConfiguration.class,
|
||||
EmbeddedDataSourceConfiguration.class,
|
||||
DataSourceTransactionManagerAutoConfiguration.class,
|
||||
TransactionAutoConfiguration.class);
|
||||
@ -99,8 +94,6 @@ public class DataSourceTransactionManagerAutoConfigurationTests {
|
||||
this.context.refresh();
|
||||
assertThat(this.context.getBeansOfType(PlatformTransactionManager.class))
|
||||
.isEmpty();
|
||||
assertThat(this.context.getBean(AbstractTransactionManagementConfiguration.class))
|
||||
.isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -130,11 +123,6 @@ public class DataSourceTransactionManagerAutoConfigurationTests {
|
||||
assertThat(transactionManager.isRollbackOnCommitFailure()).isTrue();
|
||||
}
|
||||
|
||||
@EnableTransactionManagement
|
||||
protected static class SwitchTransactionsOn {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
protected static class TransactionManagerConfiguration {
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2016 the original author or authors.
|
||||
* Copyright 2012-2017 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.
|
||||
@ -19,17 +19,25 @@ package org.springframework.boot.autoconfigure.transaction;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
|
||||
import org.springframework.boot.test.util.EnvironmentTestUtils;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@ -60,8 +68,8 @@ public class TransactionAutoConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void singleTransactionManager() {
|
||||
load(DataSourceAutoConfiguration.class,
|
||||
DataSourceTransactionManagerAutoConfiguration.class);
|
||||
load(new Class<?>[] { DataSourceAutoConfiguration.class,
|
||||
DataSourceTransactionManagerAutoConfiguration.class });
|
||||
PlatformTransactionManager transactionManager = this.context
|
||||
.getBean(PlatformTransactionManager.class);
|
||||
TransactionTemplate transactionTemplate = this.context
|
||||
@ -93,15 +101,53 @@ public class TransactionAutoConfigurationTests {
|
||||
List<?> field = (List<?>) ReflectionTestUtils.getField(customizers,
|
||||
"customizers");
|
||||
assertThat(field).hasSize(1).first().isInstanceOf(TransactionProperties.class);
|
||||
|
||||
}
|
||||
|
||||
private void load(Class<?>... configs) {
|
||||
|
||||
@Test
|
||||
public void transactionNotManagedWithNoTransactionManager() {
|
||||
load(BaseConfiguration.class);
|
||||
assertThat(this.context.getBean(TransactionalService.class)
|
||||
.isTransactionActive()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void transactionManagerUsesCglibByDefault() {
|
||||
load(TransactionManagersConfiguration.class);
|
||||
assertThat(this.context.getBean(AnotherServiceImpl.class)
|
||||
.isTransactionActive()).isTrue();
|
||||
assertThat(this.context.getBeansOfType(TransactionalServiceImpl.class)).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void transactionManagerCanBeConfiguredToJdkProxy() {
|
||||
load(TransactionManagersConfiguration.class, "spring.aop.proxy-target-class=false");
|
||||
assertThat(this.context.getBean(AnotherService.class)
|
||||
.isTransactionActive()).isTrue();
|
||||
assertThat(this.context.getBeansOfType(AnotherServiceImpl.class)).hasSize(0);
|
||||
assertThat(this.context.getBeansOfType(TransactionalServiceImpl.class)).hasSize(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customEnableTransactionManagementTakesPrecedence() {
|
||||
load(new Class<?>[] { CustomTransactionManagementConfiguration.class,
|
||||
TransactionManagersConfiguration.class },
|
||||
"spring.aop.proxy-target-class=true");
|
||||
assertThat(this.context.getBean(AnotherService.class)
|
||||
.isTransactionActive()).isTrue();
|
||||
assertThat(this.context.getBeansOfType(AnotherServiceImpl.class)).hasSize(0);
|
||||
assertThat(this.context.getBeansOfType(TransactionalServiceImpl.class)).hasSize(0);
|
||||
}
|
||||
|
||||
private void load(Class<?> config, String... environment) {
|
||||
load(new Class<?>[] { config }, environment);
|
||||
}
|
||||
|
||||
private void load(Class<?>[] configs, String... environment) {
|
||||
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
|
||||
applicationContext.register(configs);
|
||||
applicationContext.register(TransactionAutoConfiguration.class);
|
||||
EnvironmentTestUtils.addEnvironment(applicationContext,
|
||||
"spring.datasource.initialize:false");
|
||||
EnvironmentTestUtils.addEnvironment(applicationContext, environment);
|
||||
applicationContext.refresh();
|
||||
this.context = applicationContext;
|
||||
}
|
||||
@ -141,4 +187,74 @@ public class TransactionAutoConfigurationTests {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class BaseConfiguration {
|
||||
|
||||
@Bean
|
||||
public TransactionalService transactionalService() {
|
||||
return new TransactionalServiceImpl();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AnotherServiceImpl anotherService() {
|
||||
return new AnotherServiceImpl();
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import(BaseConfiguration.class)
|
||||
static class TransactionManagersConfiguration {
|
||||
|
||||
@Bean
|
||||
public DataSourceTransactionManager transactionManager() {
|
||||
return new DataSourceTransactionManager(dataSource());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DataSource dataSource() {
|
||||
return DataSourceBuilder.create()
|
||||
.driverClassName("org.hsqldb.jdbc.JDBCDriver")
|
||||
.url("jdbc:hsqldb:mem:tx").username("sa").build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableTransactionManagement(proxyTargetClass = false)
|
||||
static class CustomTransactionManagementConfiguration {
|
||||
|
||||
}
|
||||
|
||||
interface TransactionalService {
|
||||
|
||||
@Transactional
|
||||
boolean isTransactionActive();
|
||||
|
||||
}
|
||||
|
||||
static class TransactionalServiceImpl implements TransactionalService {
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isTransactionActive() {
|
||||
return TransactionSynchronizationManager.isActualTransactionActive();
|
||||
}
|
||||
}
|
||||
|
||||
interface AnotherService {
|
||||
|
||||
boolean isTransactionActive();
|
||||
|
||||
}
|
||||
|
||||
static class AnotherServiceImpl implements AnotherService {
|
||||
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public boolean isTransactionActive() {
|
||||
return TransactionSynchronizationManager.isActualTransactionActive();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2016 the original author or authors.
|
||||
* Copyright 2012-2017 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.
|
||||
@ -32,7 +32,6 @@ import org.springframework.data.gemfire.GemfireTransactionManager;
|
||||
import org.springframework.data.gemfire.RegionAttributesFactoryBean;
|
||||
import org.springframework.data.gemfire.ReplicatedRegionFactoryBean;
|
||||
import org.springframework.data.gemfire.repository.config.EnableGemfireRepositories;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
/**
|
||||
* The GemstoneAppConfiguration class for allowing Spring Boot to pick up additional
|
||||
@ -43,7 +42,6 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
*/
|
||||
@SpringBootApplication
|
||||
@EnableGemfireRepositories
|
||||
@EnableTransactionManagement
|
||||
@EnableConfigurationProperties(SampleDataGemFireProperties.class)
|
||||
public class SampleDataGemFireApplication {
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user