Fix APC registration for @EnableTransactionManagement
Prior to this change, @EnableTransactionManagement (via the ProxyTransactionManagementConfiguration class) did not properly register its auto-proxy creator through the usual AopConfigUtils methods. It was trying to register the APC as a normal @Bean method, but this causes issues (SPR-8494) with the logic in AopConfigUtils#registerOrEscalateApcAsRequired, which expects the APC bean definition to have a beanClassName property. When the APC is registered via a @Bean definition, it is actually a factoryBean/factoryMethod situation with no directly resolvable beanClass/beanClassName. Rather than trying to rework how AopConfigUtils works, a @PostConstruct method has been added to ProxyTransactionManagementConfiguration to call the usual AopConfigUtils registration methods. Issue: SPR-8411, SPR-8494
This commit is contained in:
parent
5aa24af126
commit
f1ef3e4dcd
|
|
@ -22,6 +22,7 @@ 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;
|
||||
|
||||
|
|
@ -32,9 +33,14 @@ import org.junit.Test;
|
|||
import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.framework.Advised;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.concurrent.ConcurrentMapCache;
|
||||
import org.springframework.cache.support.SimpleCacheManager;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.ImportResource;
|
||||
import org.springframework.context.config.AdviceMode;
|
||||
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
|
||||
|
|
@ -152,6 +158,38 @@ public class EnableTransactionManagementIntegrationTests {
|
|||
assertThat(txManager2.rollbacks, equalTo(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void apcEscalation() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(EnableTxAndCachingConfig.class);
|
||||
ctx.refresh();
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableTransactionManagement
|
||||
@ImportResource("org/springframework/transaction/annotation/enable-caching.xml")
|
||||
static class EnableTxAndCachingConfig {
|
||||
@Bean
|
||||
public PlatformTransactionManager txManager() {
|
||||
return new CallCountingTransactionManager();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FooRepository fooRepository() {
|
||||
return new DummyFooRepository();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CacheManager cacheManager() {
|
||||
SimpleCacheManager mgr = new SimpleCacheManager();
|
||||
ArrayList<Cache> caches = new ArrayList<Cache>();
|
||||
caches.add(new ConcurrentMapCache());
|
||||
mgr.setCaches(caches);
|
||||
return mgr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableTransactionManagement
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:cache="http://www.springframework.org/schema/cache"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">
|
||||
|
||||
<cache:annotation-driven/>
|
||||
|
||||
</beans>
|
||||
|
|
@ -16,9 +16,12 @@
|
|||
|
||||
package org.springframework.transaction.annotation;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import org.springframework.aop.config.AopConfigUtils;
|
||||
import org.springframework.aop.framework.autoproxy.InfrastructureAdvisorAutoProxyCreator;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Role;
|
||||
|
|
@ -39,6 +42,17 @@ import org.springframework.transaction.interceptor.TransactionInterceptor;
|
|||
@Configuration
|
||||
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
|
||||
|
||||
@Autowired
|
||||
private DefaultListableBeanFactory registry;
|
||||
|
||||
@PostConstruct
|
||||
public void registerAutoProxyCreator() {
|
||||
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
|
||||
if ((Boolean)enableTx.get("proxyTargetClass")) {
|
||||
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
|
||||
}
|
||||
}
|
||||
|
||||
@Bean(name=TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
|
||||
|
|
@ -67,12 +81,4 @@ public class ProxyTransactionManagementConfiguration extends AbstractTransaction
|
|||
return interceptor;
|
||||
}
|
||||
|
||||
// TODO: deal with escalation of APCs
|
||||
@Bean(name=AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME)
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
public InfrastructureAdvisorAutoProxyCreator apc() {
|
||||
InfrastructureAdvisorAutoProxyCreator apc = new InfrastructureAdvisorAutoProxyCreator();
|
||||
apc.setProxyTargetClass((Boolean) this.enableTx.get("proxyTargetClass"));
|
||||
return apc;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue