13 changed files with 930 additions and 28 deletions
@ -0,0 +1,38 @@
@@ -0,0 +1,38 @@
|
||||
/* |
||||
* Copyright 2002-2011 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.AbstractTransactionManagementConfiguration; |
||||
import org.springframework.transaction.config.TransactionManagementConfigUtils; |
||||
|
||||
@Configuration |
||||
public class AspectJTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration { |
||||
|
||||
@Bean(name=TransactionManagementConfigUtils.TRANSACTION_ASPECT_BEAN_NAME) |
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE) |
||||
public AnnotationTransactionAspect transactionAspect() { |
||||
AnnotationTransactionAspect txAspect = AnnotationTransactionAspect.aspectOf(); |
||||
if (this.txManager != null) { |
||||
txAspect.setTransactionManager(this.txManager); |
||||
} |
||||
return txAspect; |
||||
} |
||||
} |
||||
@ -0,0 +1,59 @@
@@ -0,0 +1,59 @@
|
||||
package org.springframework.transaction; |
||||
/* |
||||
* Copyright 2002-2007 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. |
||||
*/ |
||||
|
||||
|
||||
|
||||
import org.springframework.transaction.support.AbstractPlatformTransactionManager; |
||||
import org.springframework.transaction.support.DefaultTransactionStatus; |
||||
|
||||
/** |
||||
* @author Rod Johnson |
||||
* @author Juergen Hoeller |
||||
*/ |
||||
public class CallCountingTransactionManager extends AbstractPlatformTransactionManager { |
||||
|
||||
public TransactionDefinition lastDefinition; |
||||
public int begun; |
||||
public int commits; |
||||
public int rollbacks; |
||||
public int inflight; |
||||
|
||||
protected Object doGetTransaction() { |
||||
return new Object(); |
||||
} |
||||
|
||||
protected void doBegin(Object transaction, TransactionDefinition definition) { |
||||
this.lastDefinition = definition; |
||||
++begun; |
||||
++inflight; |
||||
} |
||||
|
||||
protected void doCommit(DefaultTransactionStatus status) { |
||||
++commits; |
||||
--inflight; |
||||
} |
||||
|
||||
protected void doRollback(DefaultTransactionStatus status) { |
||||
++rollbacks; |
||||
--inflight; |
||||
} |
||||
|
||||
public void clear() { |
||||
begun = commits = rollbacks = inflight = 0; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,306 @@
@@ -0,0 +1,306 @@
|
||||
/* |
||||
* Copyright 2002-2011 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.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.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; |
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.context.config.AdviceMode; |
||||
import org.springframework.jdbc.datasource.DataSourceTransactionManager; |
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; |
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; |
||||
import org.springframework.stereotype.Repository; |
||||
import org.springframework.transaction.CallCountingTransactionManager; |
||||
import org.springframework.transaction.PlatformTransactionManager; |
||||
import org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor; |
||||
|
||||
/** |
||||
* Integration tests for the @EnableTransactionManagement annotation. |
||||
* |
||||
* @author Chris Beams |
||||
* @since 3.1 |
||||
*/ |
||||
public class EnableTransactionManagementIntegrationTests { |
||||
|
||||
@Test |
||||
public void repositoryIsNotTxProxy() { |
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); |
||||
ctx.register(Config.class); |
||||
ctx.refresh(); |
||||
|
||||
try { |
||||
assertTxProxying(ctx); |
||||
fail("expected exception"); |
||||
} catch (AssertionError ex) { |
||||
assertThat(ex.getMessage(), equalTo("FooRepository is not a TX proxy")); |
||||
} |
||||
} |
||||
|
||||
@Test |
||||
public void repositoryIsTxProxy_withDefaultTxManagerName() { |
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); |
||||
ctx.register(Config.class, DefaultTxManagerNameConfig.class); |
||||
ctx.refresh(); |
||||
|
||||
assertTxProxying(ctx); |
||||
} |
||||
|
||||
@Test |
||||
public void repositoryIsTxProxy_withCustomTxManagerName() { |
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); |
||||
ctx.register(Config.class, CustomTxManagerNameConfig.class); |
||||
ctx.refresh(); |
||||
|
||||
assertTxProxying(ctx); |
||||
} |
||||
|
||||
@Ignore @Test // TODO SPR-8207
|
||||
public void repositoryIsTxProxy_withNonConventionalTxManagerName_fallsBackToByTypeLookup() { |
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); |
||||
ctx.register(Config.class, NonConventionalTxManagerNameConfig.class); |
||||
ctx.refresh(); |
||||
|
||||
assertTxProxying(ctx); |
||||
} |
||||
|
||||
@Test |
||||
public void repositoryIsClassBasedTxProxy() { |
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); |
||||
ctx.register(Config.class, ProxyTargetClassTxConfig.class); |
||||
ctx.refresh(); |
||||
|
||||
assertTxProxying(ctx); |
||||
assertThat(AopUtils.isCglibProxy(ctx.getBean(FooRepository.class)), is(true)); |
||||
} |
||||
|
||||
@Test |
||||
public void repositoryUsesAspectJAdviceMode() { |
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); |
||||
ctx.register(Config.class, AspectJTxConfig.class); |
||||
try { |
||||
ctx.refresh(); |
||||
} catch (Exception ex) { |
||||
// 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().endsWith("AspectJTransactionManagementConfiguration.class] cannot be opened because it does not exist")); |
||||
} |
||||
} |
||||
|
||||
@Test |
||||
public void implicitTxManager() { |
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); |
||||
ctx.register(ImplicitTxManagerConfig.class); |
||||
ctx.refresh(); |
||||
|
||||
FooRepository fooRepository = ctx.getBean(FooRepository.class); |
||||
fooRepository.findAll(); |
||||
|
||||
CallCountingTransactionManager txManager = ctx.getBean(CallCountingTransactionManager.class); |
||||
assertThat(txManager.begun, equalTo(1)); |
||||
assertThat(txManager.commits, equalTo(1)); |
||||
assertThat(txManager.rollbacks, equalTo(0)); |
||||
} |
||||
|
||||
@Test |
||||
public void explicitTxManager() { |
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); |
||||
ctx.register(ExplicitTxManagerConfig.class); |
||||
ctx.refresh(); |
||||
|
||||
FooRepository fooRepository = ctx.getBean(FooRepository.class); |
||||
fooRepository.findAll(); |
||||
|
||||
CallCountingTransactionManager txManager1 = ctx.getBean("txManager1", CallCountingTransactionManager.class); |
||||
assertThat(txManager1.begun, equalTo(1)); |
||||
assertThat(txManager1.commits, equalTo(1)); |
||||
assertThat(txManager1.rollbacks, equalTo(0)); |
||||
|
||||
CallCountingTransactionManager txManager2 = ctx.getBean("txManager2", CallCountingTransactionManager.class); |
||||
assertThat(txManager2.begun, equalTo(0)); |
||||
assertThat(txManager2.commits, equalTo(0)); |
||||
assertThat(txManager2.rollbacks, equalTo(0)); |
||||
} |
||||
|
||||
|
||||
@Configuration |
||||
@EnableTransactionManagement |
||||
static class ImplicitTxManagerConfig { |
||||
@Bean |
||||
public PlatformTransactionManager txManager() { |
||||
return new CallCountingTransactionManager(); |
||||
} |
||||
|
||||
@Bean |
||||
public FooRepository fooRepository() { |
||||
return new DummyFooRepository(); |
||||
} |
||||
} |
||||
|
||||
|
||||
@Configuration |
||||
@EnableTransactionManagement |
||||
static class ExplicitTxManagerConfig implements TransactionManagementConfigurer { |
||||
@Bean |
||||
public PlatformTransactionManager txManager1() { |
||||
return new CallCountingTransactionManager(); |
||||
} |
||||
|
||||
@Bean |
||||
public PlatformTransactionManager txManager2() { |
||||
return new CallCountingTransactionManager(); |
||||
} |
||||
|
||||
public PlatformTransactionManager createTransactionManager() { |
||||
return txManager1(); |
||||
} |
||||
|
||||
@Bean |
||||
public FooRepository fooRepository() { |
||||
return new DummyFooRepository(); |
||||
} |
||||
} |
||||
|
||||
private void assertTxProxying(AnnotationConfigApplicationContext ctx) { |
||||
FooRepository repo = ctx.getBean(FooRepository.class); |
||||
|
||||
boolean isTxProxy = false; |
||||
if (AopUtils.isAopProxy(repo)) { |
||||
for (Advisor advisor : ((Advised)repo).getAdvisors()) { |
||||
if (advisor instanceof BeanFactoryTransactionAttributeSourceAdvisor) { |
||||
isTxProxy = true; |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
assertTrue("FooRepository is not a TX proxy", isTxProxy); |
||||
|
||||
// trigger a transaction
|
||||
repo.findAll(); |
||||
} |
||||
|
||||
|
||||
@Configuration |
||||
@EnableTransactionManagement |
||||
static class DefaultTxManagerNameConfig { |
||||
@Bean |
||||
PlatformTransactionManager transactionManager(DataSource dataSource) { |
||||
return new DataSourceTransactionManager(dataSource); |
||||
} |
||||
} |
||||
|
||||
|
||||
@Configuration |
||||
@EnableTransactionManagement |
||||
static class CustomTxManagerNameConfig { |
||||
@Bean |
||||
PlatformTransactionManager txManager(DataSource dataSource) { |
||||
return new DataSourceTransactionManager(dataSource); |
||||
} |
||||
} |
||||
|
||||
|
||||
@Configuration |
||||
@EnableTransactionManagement |
||||
static class NonConventionalTxManagerNameConfig { |
||||
@Bean |
||||
PlatformTransactionManager txManager(DataSource dataSource) { |
||||
return new DataSourceTransactionManager(dataSource); |
||||
} |
||||
} |
||||
|
||||
|
||||
@Configuration |
||||
@EnableTransactionManagement(proxyTargetClass=true) |
||||
static class ProxyTargetClassTxConfig { |
||||
@Bean |
||||
PlatformTransactionManager transactionManager(DataSource dataSource) { |
||||
return new DataSourceTransactionManager(dataSource); |
||||
} |
||||
} |
||||
|
||||
|
||||
@Configuration |
||||
@EnableTransactionManagement(mode=AdviceMode.ASPECTJ) |
||||
static class AspectJTxConfig { |
||||
@Bean |
||||
PlatformTransactionManager transactionManager(DataSource dataSource) { |
||||
return new DataSourceTransactionManager(dataSource); |
||||
} |
||||
} |
||||
|
||||
|
||||
@Configuration |
||||
static class Config { |
||||
@Bean |
||||
FooRepository fooRepository() { |
||||
JdbcFooRepository repos = new JdbcFooRepository(); |
||||
repos.setDataSource(dataSource()); |
||||
return repos; |
||||
} |
||||
|
||||
@Bean |
||||
DataSource dataSource() { |
||||
return new EmbeddedDatabaseBuilder() |
||||
.setType(EmbeddedDatabaseType.HSQL) |
||||
.build(); |
||||
} |
||||
} |
||||
|
||||
|
||||
interface FooRepository { |
||||
List<Object> findAll(); |
||||
} |
||||
|
||||
|
||||
@Repository |
||||
static class JdbcFooRepository implements FooRepository { |
||||
|
||||
public void setDataSource(DataSource dataSource) { |
||||
} |
||||
|
||||
@Transactional |
||||
public List<Object> findAll() { |
||||
return Collections.emptyList(); |
||||
} |
||||
} |
||||
|
||||
@Repository |
||||
static class DummyFooRepository implements FooRepository { |
||||
|
||||
@Transactional |
||||
public List<Object> findAll() { |
||||
return Collections.emptyList(); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,64 @@
@@ -0,0 +1,64 @@
|
||||
/* |
||||
* Copyright 2002-2011 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.annotation; |
||||
|
||||
import java.util.Collection; |
||||
import java.util.Map; |
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.context.annotation.ImportAware; |
||||
import org.springframework.core.type.AnnotationMetadata; |
||||
import org.springframework.transaction.PlatformTransactionManager; |
||||
import org.springframework.util.Assert; |
||||
|
||||
/** |
||||
* Abstract base class providing common structure for enabling Spring's annotation- |
||||
* driven transaction management capability. |
||||
* |
||||
* @author Chris Beams |
||||
* @since 3.1 |
||||
* @see EnableTransactionManagement |
||||
*/ |
||||
@Configuration |
||||
public abstract class AbstractTransactionManagementConfiguration implements ImportAware { |
||||
|
||||
protected Map<String, Object> enableTx; |
||||
protected PlatformTransactionManager txManager; |
||||
|
||||
public void setImportMetadata(AnnotationMetadata importMetadata) { |
||||
enableTx = importMetadata.getAnnotationAttributes(EnableTransactionManagement.class.getName(), false); |
||||
Assert.notNull(enableTx, |
||||
"@EnableTransactionManagement is not present on importing class " + |
||||
importMetadata.getClassName()); |
||||
} |
||||
|
||||
@Autowired(required=false) |
||||
void setConfigurers(Collection<TransactionManagementConfigurer> configurers) { |
||||
if (configurers == null || configurers.isEmpty()) { |
||||
return; |
||||
} |
||||
|
||||
if (configurers.size() > 1) { |
||||
throw new IllegalStateException("only one TransactionManagementConfigurer may exist"); |
||||
} |
||||
|
||||
TransactionManagementConfigurer configurer = configurers.iterator().next(); |
||||
this.txManager = configurer.createTransactionManager(); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,58 @@
@@ -0,0 +1,58 @@
|
||||
/* |
||||
* Copyright 2002-2011 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.annotation; |
||||
|
||||
import java.lang.annotation.Documented; |
||||
import java.lang.annotation.ElementType; |
||||
import java.lang.annotation.Retention; |
||||
import java.lang.annotation.RetentionPolicy; |
||||
import java.lang.annotation.Target; |
||||
|
||||
import org.springframework.context.annotation.Import; |
||||
import org.springframework.context.config.AdviceMode; |
||||
import org.springframework.core.Ordered; |
||||
|
||||
@Target(ElementType.TYPE) |
||||
@Retention(RetentionPolicy.RUNTIME) |
||||
@Documented |
||||
@Import(TransactionManagementConfigurationSelector.class) |
||||
public @interface EnableTransactionManagement { |
||||
|
||||
/** |
||||
* Indicate whether class-based (CGLIB) proxies are to be created as opposed |
||||
* to standard Java interface-based proxies. The default is {@code false}. |
||||
* |
||||
* <p>Note: Class-based proxies require the {@link Transactional @Transactional} |
||||
* annotation to be defined on the concrete class. Annotations in interfaces will |
||||
* not work in that case (they will rather only work with interface-based proxies)! |
||||
*/ |
||||
boolean proxyTargetClass() default false; |
||||
|
||||
/** |
||||
* Indicate how transactional advice should be applied. |
||||
* The default is {@link AdviceMode.PROXY}. |
||||
* @see AdviceMode |
||||
*/ |
||||
AdviceMode mode() default AdviceMode.PROXY; |
||||
|
||||
/** |
||||
* Indicate the ordering of the execution of the transaction advisor |
||||
* when multiple advices are applied at a specific joinpoint. |
||||
* The default is to not explicitly order the advisor. |
||||
*/ |
||||
int order() default Ordered.NOT_ORDERED; |
||||
} |
||||
@ -0,0 +1,73 @@
@@ -0,0 +1,73 @@
|
||||
/* |
||||
* Copyright 2002-2011 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.annotation; |
||||
|
||||
import org.springframework.aop.config.AopConfigUtils; |
||||
import org.springframework.aop.framework.autoproxy.InfrastructureAdvisorAutoProxyCreator; |
||||
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.core.Ordered; |
||||
import org.springframework.transaction.config.TransactionManagementConfigUtils; |
||||
import org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor; |
||||
import org.springframework.transaction.interceptor.TransactionAttributeSource; |
||||
import org.springframework.transaction.interceptor.TransactionInterceptor; |
||||
|
||||
@Configuration |
||||
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration { |
||||
|
||||
@Bean(name=TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME) |
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE) |
||||
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() { |
||||
BeanFactoryTransactionAttributeSourceAdvisor advisor = |
||||
new BeanFactoryTransactionAttributeSourceAdvisor(); |
||||
advisor.setTransactionAttributeSource(transactionAttributeSource()); |
||||
advisor.setAdvice(transactionInterceptor()); |
||||
int order = (Integer)this.enableTx.get("order"); |
||||
if (order != Ordered.NOT_ORDERED) { |
||||
advisor.setOrder(order); |
||||
} |
||||
return advisor; |
||||
} |
||||
|
||||
@Bean |
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE) |
||||
public TransactionAttributeSource transactionAttributeSource() { |
||||
return new AnnotationTransactionAttributeSource(); |
||||
} |
||||
|
||||
@Bean |
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE) |
||||
public TransactionInterceptor transactionInterceptor() { |
||||
TransactionInterceptor interceptor = new TransactionInterceptor(); |
||||
interceptor.setTransactionAttributeSource(transactionAttributeSource()); |
||||
if (this.txManager != null) { |
||||
interceptor.setTransactionManager(this.txManager); |
||||
} |
||||
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; |
||||
} |
||||
} |
||||
@ -0,0 +1,45 @@
@@ -0,0 +1,45 @@
|
||||
/* |
||||
* Copyright 2002-2011 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.annotation; |
||||
|
||||
import java.util.Map; |
||||
|
||||
import org.springframework.context.annotation.ImportSelector; |
||||
import org.springframework.context.config.AdviceMode; |
||||
import org.springframework.core.type.AnnotationMetadata; |
||||
import org.springframework.util.Assert; |
||||
|
||||
public class TransactionManagementConfigurationSelector implements ImportSelector { |
||||
|
||||
public String[] selectImports(AnnotationMetadata importingClassMetadata) { |
||||
Map<String, Object> enableTx = |
||||
importingClassMetadata.getAnnotationAttributes(EnableTransactionManagement.class.getName()); |
||||
Assert.notNull(enableTx, |
||||
"@EnableTransactionManagement is not present on importing class " + |
||||
importingClassMetadata.getClassName()); |
||||
|
||||
switch ((AdviceMode) enableTx.get("mode")) { |
||||
case PROXY: |
||||
return new String[] {ProxyTransactionManagementConfiguration.class.getName()}; |
||||
case ASPECTJ: |
||||
return new String[] {"org.springframework.transaction.aspectj.AspectJTransactionManagementConfiguration"}; |
||||
default: |
||||
throw new IllegalArgumentException("Unknown AdviceMode " + enableTx.get("mode")); |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,25 @@
@@ -0,0 +1,25 @@
|
||||
/* |
||||
* Copyright 2002-2011 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.annotation; |
||||
|
||||
import org.springframework.transaction.PlatformTransactionManager; |
||||
|
||||
public interface TransactionManagementConfigurer { |
||||
|
||||
PlatformTransactionManager createTransactionManager(); |
||||
|
||||
} |
||||
@ -0,0 +1,39 @@
@@ -0,0 +1,39 @@
|
||||
/* |
||||
* Copyright 2002-2011 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.config; |
||||
|
||||
public abstract class TransactionManagementConfigUtils { |
||||
|
||||
/** |
||||
* The bean name of the internally managed transaction advisor (used when mode == PROXY). |
||||
*/ |
||||
public static final String TRANSACTION_ADVISOR_BEAN_NAME = |
||||
"org.springframework.transaction.config.internalTransactionAdvisor"; |
||||
|
||||
/** |
||||
* The bean name of the internally managed transaction aspect (used when mode == ASPECTJ). |
||||
*/ |
||||
public static final String TRANSACTION_ASPECT_BEAN_NAME = |
||||
"org.springframework.transaction.config.internalTransactionAspect"; |
||||
|
||||
/** |
||||
* The class name of the AspectJ transaction management aspect. |
||||
*/ |
||||
public static final String TRANSACTION_ASPECT_CLASS_NAME = |
||||
"org.springframework.transaction.aspectj.AnnotationTransactionAspect"; |
||||
|
||||
} |
||||
@ -0,0 +1,134 @@
@@ -0,0 +1,134 @@
|
||||
/* |
||||
* Copyright 2002-2011 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.annotation; |
||||
|
||||
import static org.hamcrest.CoreMatchers.is; |
||||
import static org.junit.Assert.assertThat; |
||||
import static org.junit.Assert.fail; |
||||
|
||||
import java.util.Map; |
||||
|
||||
import org.junit.Test; |
||||
import org.springframework.aop.support.AopUtils; |
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.context.config.AdviceMode; |
||||
import org.springframework.stereotype.Service; |
||||
import org.springframework.transaction.CallCountingTransactionManager; |
||||
import org.springframework.transaction.PlatformTransactionManager; |
||||
import org.springframework.transaction.annotation.AnnotationTransactionNamespaceHandlerTests.TransactionalTestBean; |
||||
|
||||
/** |
||||
* Tests demonstrating use of @EnableTransactionManagement @Configuration classes. |
||||
* |
||||
* @author Chris Beams |
||||
* @since 3.1 |
||||
*/ |
||||
public class EnableTransactionManagementTests { |
||||
|
||||
@Test |
||||
public void transactionProxyIsCreated() { |
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); |
||||
ctx.register(EnableTxConfig.class, TxManagerConfig.class); |
||||
ctx.refresh(); |
||||
TransactionalTestBean bean = ctx.getBean(TransactionalTestBean.class); |
||||
assertThat("testBean is not a proxy", AopUtils.isAopProxy(bean), is(true)); |
||||
Map<?,?> services = ctx.getBeansWithAnnotation(Service.class); |
||||
assertThat("Stereotype annotation not visible", services.containsKey("testBean"), is(true)); |
||||
} |
||||
|
||||
@Test |
||||
public void txManagerIsResolvedOnInvocationOfTransactionalMethod() { |
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); |
||||
ctx.register(EnableTxConfig.class, TxManagerConfig.class); |
||||
ctx.refresh(); |
||||
TransactionalTestBean bean = ctx.getBean(TransactionalTestBean.class); |
||||
|
||||
// invoke a transactional method, causing the PlatformTransactionManager bean to be resolved.
|
||||
bean.findAllFoos(); |
||||
} |
||||
|
||||
@Test |
||||
public void txManagerIsResolvedCorrectlyWhenMultipleManagersArePresent() { |
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); |
||||
ctx.register(EnableTxConfig.class, MultiTxManagerConfig.class); |
||||
ctx.refresh(); |
||||
TransactionalTestBean bean = ctx.getBean(TransactionalTestBean.class); |
||||
|
||||
// invoke a transactional method, causing the PlatformTransactionManager bean to be resolved.
|
||||
bean.findAllFoos(); |
||||
} |
||||
|
||||
/** |
||||
* A cheap test just to prove that in ASPECTJ mode, the AnnotationTransactionAspect does indeed |
||||
* get loaded -- or in this case, attempted to be loaded at which point the test fails. |
||||
*/ |
||||
@Test |
||||
public void proxyTypeAspectJCausesRegistrationOfAnnotationTransactionAspect() { |
||||
try { |
||||
new AnnotationConfigApplicationContext(EnableAspectJTxConfig.class, TxManagerConfig.class); |
||||
fail("should have thrown CNFE when trying to load AnnotationTransactionAspect. " + |
||||
"Do you actually have org.springframework.aspects on the classpath?"); |
||||
} catch (Exception ex) { |
||||
System.out.println(ex); |
||||
assertThat(ex.getMessage().endsWith("AspectJTransactionManagementConfiguration.class] cannot be opened because it does not exist"), is(true)); |
||||
} |
||||
} |
||||
|
||||
|
||||
@Configuration |
||||
@EnableTransactionManagement |
||||
static class EnableTxConfig { |
||||
} |
||||
|
||||
|
||||
@Configuration |
||||
@EnableTransactionManagement(mode=AdviceMode.ASPECTJ) |
||||
static class EnableAspectJTxConfig { |
||||
} |
||||
|
||||
|
||||
@Configuration |
||||
static class TxManagerConfig { |
||||
|
||||
@Bean |
||||
public TransactionalTestBean testBean() { |
||||
return new TransactionalTestBean(); |
||||
} |
||||
|
||||
@Bean |
||||
public PlatformTransactionManager txManager() { |
||||
return new CallCountingTransactionManager(); |
||||
} |
||||
|
||||
} |
||||
|
||||
|
||||
@Configuration |
||||
static class MultiTxManagerConfig extends TxManagerConfig implements TransactionManagementConfigurer { |
||||
|
||||
@Bean |
||||
public PlatformTransactionManager txManager2() { |
||||
return new CallCountingTransactionManager(); |
||||
} |
||||
|
||||
public PlatformTransactionManager createTransactionManager() { |
||||
return txManager2(); |
||||
} |
||||
} |
||||
} |
||||
Loading…
Reference in new issue