Introduce @EnableTransactionManagement
This commit is contained in:
@@ -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 @@
|
||||
/*
|
||||
* 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 @@
|
||||
/*
|
||||
* 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 @@
|
||||
/*
|
||||
* 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 @@
|
||||
/*
|
||||
* 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();
|
||||
|
||||
}
|
||||
@@ -26,10 +26,9 @@ import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.context.config.AbstractSpecificationBeanDefinitionParser;
|
||||
import org.springframework.context.config.FeatureSpecification;
|
||||
import org.springframework.transaction.annotation.TransactionManagementCapability;
|
||||
import org.w3c.dom.Element;
|
||||
import org.springframework.transaction.annotation.AnnotationTransactionAttributeSource;
|
||||
import org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor;
|
||||
import org.springframework.transaction.interceptor.TransactionInterceptor;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.beans.factory.xml.BeanDefinitionParser
|
||||
@@ -53,20 +52,20 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
|
||||
/**
|
||||
* The bean name of the internally managed transaction advisor (mode="proxy").
|
||||
* @deprecated as of Spring 3.1 in favor of
|
||||
* {@link TransactionManagementCapability#TRANSACTION_ADVISOR_BEAN_NAME}
|
||||
* {@link TransactionManagementConfigUtils#TRANSACTION_ADVISOR_BEAN_NAME}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String TRANSACTION_ADVISOR_BEAN_NAME =
|
||||
TransactionManagementCapability.TRANSACTION_ADVISOR_BEAN_NAME;
|
||||
TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;
|
||||
|
||||
/**
|
||||
* The bean name of the internally managed transaction aspect (mode="aspectj").
|
||||
* @deprecated as of Spring 3.1 in favor of
|
||||
* {@link TransactionManagementCapability#TRANSACTION_ASPECT_BEAN_NAME}
|
||||
* {@link TransactionManagementConfigUtils#TRANSACTION_ASPECT_BEAN_NAME}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String TRANSACTION_ASPECT_BEAN_NAME =
|
||||
TransactionManagementCapability.TRANSACTION_ASPECT_BEAN_NAME;
|
||||
TransactionManagementConfigUtils.TRANSACTION_ASPECT_BEAN_NAME;
|
||||
|
||||
|
||||
/**
|
||||
@@ -74,12 +73,81 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
|
||||
* {@link AopNamespaceUtils#registerAutoProxyCreatorIfNecessary register an AutoProxyCreator}
|
||||
* with the container as necessary.
|
||||
*/
|
||||
@Override
|
||||
protected FeatureSpecification doParse(Element element, ParserContext parserContext) {
|
||||
return new TxAnnotationDriven(element.getAttribute("transaction-manager"))
|
||||
.order(element.getAttribute("order"))
|
||||
.mode(element.getAttribute("mode"))
|
||||
.proxyTargetClass(Boolean.valueOf(element.getAttribute("proxy-target-class")));
|
||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
String mode = element.getAttribute("mode");
|
||||
if ("aspectj".equals(mode)) {
|
||||
// mode="aspectj"
|
||||
registerTransactionAspect(element, parserContext);
|
||||
}
|
||||
else {
|
||||
// mode="proxy"
|
||||
AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void registerTransactionAspect(Element element, ParserContext parserContext) {
|
||||
String txAspectBeanName = TransactionManagementConfigUtils.TRANSACTION_ASPECT_BEAN_NAME;
|
||||
String txAspectClassName = TransactionManagementConfigUtils.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));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Inner class to just introduce an AOP framework dependency when actually in proxy mode.
|
||||
*/
|
||||
private static class AopAutoProxyConfigurer {
|
||||
|
||||
public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {
|
||||
AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);
|
||||
|
||||
String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;
|
||||
if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {
|
||||
Object eleSource = parserContext.extractSource(element);
|
||||
|
||||
// Create the TransactionAttributeSource definition.
|
||||
RootBeanDefinition sourceDef = new RootBeanDefinition(AnnotationTransactionAttributeSource.class);
|
||||
sourceDef.setSource(eleSource);
|
||||
sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);
|
||||
|
||||
// Create the TransactionInterceptor definition.
|
||||
RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);
|
||||
interceptorDef.setSource(eleSource);
|
||||
interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
registerTransactionManager(element, interceptorDef);
|
||||
interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
|
||||
String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);
|
||||
|
||||
// Create the TransactionAttributeSourceAdvisor definition.
|
||||
RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);
|
||||
advisorDef.setSource(eleSource);
|
||||
advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
|
||||
advisorDef.getPropertyValues().add("adviceBeanName", interceptorName);
|
||||
if (element.hasAttribute("order")) {
|
||||
advisorDef.getPropertyValues().add("order", element.getAttribute("order"));
|
||||
}
|
||||
parserContext.getRegistry().registerBeanDefinition(txAdvisorBeanName, advisorDef);
|
||||
|
||||
CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);
|
||||
compositeDef.addNestedComponent(new BeanComponentDefinition(sourceDef, sourceName));
|
||||
compositeDef.addNestedComponent(new BeanComponentDefinition(interceptorDef, interceptorName));
|
||||
compositeDef.addNestedComponent(new BeanComponentDefinition(advisorDef, txAdvisorBeanName));
|
||||
parserContext.registerComponent(compositeDef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user