Polish @EnableTransactionManagement Javadoc and XSD

git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@4411 50f2f4bb-b051-0410-bef5-90022cba6387
This commit is contained in:
Chris Beams 2011-06-02 14:29:06 +00:00
parent 9c73be0869
commit d9ce5f854c
7 changed files with 215 additions and 7 deletions

View File

@ -21,8 +21,19 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Role; import org.springframework.context.annotation.Role;
import org.springframework.transaction.annotation.AbstractTransactionManagementConfiguration; import org.springframework.transaction.annotation.AbstractTransactionManagementConfiguration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.TransactionManagementConfigurationSelector;
import org.springframework.transaction.config.TransactionManagementConfigUtils; import org.springframework.transaction.config.TransactionManagementConfigUtils;
/**
* {@code @Configuration} class that registers the Spring infrastructure beans necessary
* to enable AspectJ-based annotation-driven transaction management.
*
* @author Chris Beams
* @since 3.1
* @see EnableTransactionManagement
* @see TransactionManagementConfigurationSelector
*/
@Configuration @Configuration
public class AspectJTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration { public class AspectJTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {

View File

@ -27,8 +27,8 @@ import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.util.Assert; import org.springframework.util.Assert;
/** /**
* Abstract base class providing common structure for enabling Spring's annotation- * Abstract base {@code @Configuration} class providing common structure for enabling
* driven transaction management capability. * Spring's annotation-driven transaction management capability.
* *
* @author Chris Beams * @author Chris Beams
* @since 3.1 * @since 3.1

View File

@ -26,6 +26,114 @@ import org.springframework.context.annotation.Import;
import org.springframework.context.config.AdviceMode; import org.springframework.context.config.AdviceMode;
import org.springframework.core.Ordered; import org.springframework.core.Ordered;
/**
* Enables Spring's annotation-driven transaction management capability, similar to
* the support found in Spring's {@code <tx:*>} XML namespace. To be used
* on @{@link org.springframework.context.annotation.Configuration Configuration} classes
* as follows:
* <pre class="code">
* &#064;Configuration
* &#064;EnableTransactionManagement
* public class AppConfig {
* &#064;Bean
* public FooRepository fooRepository() {
* // configure and return a class having &#064;Transactional methods
* return new JdbcFooRepository(dataSource());
* }
*
* &#064;Bean
* public DataSource dataSource() {
* // configure and return the necessary JDBC DataSource
* }
*
* &#064;Bean
* public PlatformTransactionManager txManager() {
* return new DataSourceTransactionManager(dataSource());
* }
* }</pre>
*
* <p>For reference, the example above can be compared to the following Spring XML
* configuration:
* <pre class="code">
* {@code
* <beans>
* <tx:annotation-driven/>
* <bean id="fooRepository" class="com.foo.JdbcFooRepository">
* <constructor-arg ref="dataSource"/>
* </bean>
* <bean id="dataSource" class="com.vendor.VendorDataSource"/>
* <bean id="transactionManager" class="org.sfwk...DataSourceTransactionManager">
* <constructor-arg ref="dataSource"/>
* </bean>
* </beans>
* }</pre>
* In both of the scenarios above, {@code @EnableTransactionManagement} and {@code
* <tx:annotation-driven/>} are responsible for registering the necessary Spring
* components that power annotation-driven transaction management, such as the
* TransactionInterceptor and the proxy- or AspectJ-based advice that weave the
* interceptor into the call stack when {@code JdbcFooRepository}'s {@code @Transacational}
* methods are invoked.
*
* <p>A minor difference between the two examples lies in the naming of the {@code
* PlatformTransactionManager} bean: In the {@code @Bean} case, the name is
* <em>"txManager"</em> (per the name of the method); in the XML case, the name is
* <em>"transactionManager"</em>. The {@code <tx:annotation-driven/>} is hard-wired to
* look for a bean named "transactionManager" by default, however
* {@code @EnableTransactionManagement} is more flexible; it will fall back to a by-type
* lookup for any {@code PlatformTransactionManager} bean in the container. Thus the name
* can be "txManager", "transactionManager", or "tm": it simply does not matter.
*
* <p>For those that wish to establish a more direct relationship between
* {@code @EnableTransactionManagement} and the exact transaction manager bean to be used,
* the {@link TransactionManagementConfigurer} callback interface may be implemented -
* notice the {@code implements} clause and the {@code @Override}-annotated method below:
* <pre class="code">
* &#064;Configuration
* &#064;EnableTransactionManagement
* public class AppConfig implements TransactionManagementConfigurer {
* &#064;Bean
* public FooRepository fooRepository() {
* // configure and return a class having &#064;Transactional methods
* return new JdbcFooRepository(dataSource());
* }
*
* &#064;Bean
* public DataSource dataSource() {
* // configure and return the necessary JDBC DataSource
* }
*
* &#064;Bean
* public PlatformTransactionManager txManager() {
* return new DataSourceTransactionManager(dataSource());
* }
*
* &#064;Override
* public PlatformTransactionManager annotationDrivenTransactionManager() {
* return txManager();
* }
* }</pre>
* This approach may be desirable simply because it is more explicit, or it may be
* necessary in order to distinguish between two {@code PlatformTransactionManager} beans
* present in the same container. As the name suggests, the
* {@code annotationDrivenTransactionManager()} will be the one used for processing
* {@code @Transactional} methods. See {@link TransactionManagementConfigurer} Javadoc
* for further details.
*
* <p>The {@link #mode()} attribute controls how advice is applied; if the mode is
* {@link AdviceMode#PROXY} (the default), then the other attributes control the behavior
* of the proxying.
*
* <p>Note that if the {@linkplain #mode} is set to {@link AdviceMode#ASPECTJ}, then
* the {@link #proxyTargetClass()} attribute is obsolete. Note also that in this case the
* {@code spring-aspects} module JAR must be present on the classpath.<p>
*
* @author Chris Beams
* @since 3.1
* @see TransactionManagementConfigurer
* @see TransactionManagementConfigurationSelector
* @see ProxyTransactionManagementConfiguration
* @see org.springframework.transaction.aspectj.AspectJTransactionManagementConfiguration
*/
@Target(ElementType.TYPE) @Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Documented @Documented
@ -33,11 +141,12 @@ import org.springframework.core.Ordered;
public @interface EnableTransactionManagement { public @interface EnableTransactionManagement {
/** /**
* Indicate whether class-based (CGLIB) proxies are to be created as opposed * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
* to standard Java interface-based proxies. The default is {@code false}. * to standard Java interface-based proxies. The default is {@code false}. <strong>
* Applicable only if {@link #mode()} is set to {@link AdviceMode#PROXY}</strong>.
* *
* <p>Note: Class-based proxies require the {@link Transactional @Transactional} * <p>Note that subclass-based proxies require the {@link Transactional @Transactional}
* annotation to be defined on the concrete class. Annotations in interfaces will * 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)! * not work in that case (they will rather only work with interface-based proxies)!
*/ */
boolean proxyTargetClass() default false; boolean proxyTargetClass() default false;
@ -52,7 +161,7 @@ public @interface EnableTransactionManagement {
/** /**
* Indicate the ordering of the execution of the transaction advisor * Indicate the ordering of the execution of the transaction advisor
* when multiple advices are applied at a specific joinpoint. * when multiple advices are applied at a specific joinpoint.
* The default is lowest priority. * The default is {@link Ordered#LOWEST_PRECEDENCE}.
*/ */
int order() default Ordered.LOWEST_PRECEDENCE; int order() default Ordered.LOWEST_PRECEDENCE;
} }

View File

@ -27,6 +27,15 @@ import org.springframework.transaction.interceptor.BeanFactoryTransactionAttribu
import org.springframework.transaction.interceptor.TransactionAttributeSource; import org.springframework.transaction.interceptor.TransactionAttributeSource;
import org.springframework.transaction.interceptor.TransactionInterceptor; import org.springframework.transaction.interceptor.TransactionInterceptor;
/**
* {@code @Configuration} class that registers the Spring infrastructure beans necessary
* to enable proxy-based annotation-driven transaction management.
*
* @author Chris Beams
* @since 3.1
* @see EnableTransactionManagement
* @see TransactionManagementConfigurationSelector
*/
@Configuration @Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration { public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {

View File

@ -23,8 +23,26 @@ import org.springframework.context.config.AdviceMode;
import org.springframework.core.type.AnnotationMetadata; import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.Assert; import org.springframework.util.Assert;
/**
* Selects which implementation of {@link AbstractTransactionManagementConfiguration}
* should be used based on the value of {@link EnableTransactionManagement#mode} on the
* importing @{@link Configuration} class.
*
* @author Chris Beams
* @since 3.1
* @see EnableTransactionManagement
* @see AbstractTransactionManagementConfiguration
* @see ProxyTransactionManagementConfiguration
* @see org.springframework.transaction.aspectj.AspectJTransactionManagementConfiguration
*/
public class TransactionManagementConfigurationSelector implements ImportSelector { public class TransactionManagementConfigurationSelector implements ImportSelector {
/**
* Import {@link ProxyTransactionManagementConfiguration} if {@link
* EnableTransactionManagement#mode()} equals {@code PROXY}, otherwise import {@link
* org.springframework.transaction.aspectj.AspectJTransactionManagementConfiguration
* AspectJTransactionManagementConfiguration}.
*/
public String[] selectImports(AnnotationMetadata importingClassMetadata) { public String[] selectImports(AnnotationMetadata importingClassMetadata) {
Map<String, Object> enableTx = Map<String, Object> enableTx =
importingClassMetadata.getAnnotationAttributes(EnableTransactionManagement.class.getName()); importingClassMetadata.getAnnotationAttributes(EnableTransactionManagement.class.getName());

View File

@ -18,8 +18,66 @@ package org.springframework.transaction.annotation;
import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.PlatformTransactionManager;
/**
* Interface to be implemented by @{@link org.springframework.context.annotation.Configuration
* Configuration} classes annotated with @{@link EnableTransactionManagement} that wish
* or need to specify explicitly the {@link PlatformTransactionManager} bean to be used
* for annotation-driven transaction management, as opposed to the default approach of a
* by-type lookup. One reason this might be necessary is if there are two
* {@code PlatformTransactionManager} implementations present in the container.
*
* <p>See @{@link EnableTransactionManagement} for general examples and context; see
* {@link #annotationDrivenTransactionManager()} below for detailed instructions.
*
* <p>Note that in by-type lookup disambiguation cases, an alternative approach to
* implementing this interface is to simply mark one of the offending {@code
* PlatformTransactionManager} {@code @Bean} methods as @{@link
* org.springframework.context.annotation.Primary Primary}.
*
* @author Chris Beams
* @since 3.1
* @see EnableTransactionManagement
* @see org.springframework.context.annotation.Primary
*/
public interface TransactionManagementConfigurer { public interface TransactionManagementConfigurer {
/**
* Return the transaction manager bean to use for annotation-driven database
* transaction management, i.e. when processing {@code @Transactional} methods.
*
* <p>There are two basic approaches to implementing this method:
* <h3>1. Implement the method and annotate it with {@code @Bean}</h3>
* In this case, the implementing {@code @Configuration} class implements this method,
* marks it with {@code @Bean} and configures and returns the transaction manager
* directly within the method body:
* <pre class="code">
* &#064;Bean
* &#064;Override
* public PlatformTransactionManager createTransactionManager() {
* return new DataSourceTransactionManager(dataSource());
* }</pre>
* <h3>2. Implement the method without {@code @Bean} and delegate to another existing
* {@code @Bean} method</h3>
* <pre class="code">
* &#064;Bean
* public PlatformTransactionManager txManager() {
* return new DataSourceTransactionManager(dataSource());
* }
*
* &#064;Override
* public PlatformTransactionManager createTransactionManager() {
* return txManager(); // reference the existing {@code @Bean} method above
* }</pre>
*
* If taking approach #2, be sure that <em>only one</em> of the methods is marked with
* {@code @Bean}!
*
* <p>In either scenario #1 or #2, it is important that the
* {@code PlatformTransactionManager} instance is managed as a Spring bean within the
* container as all {@code PlatformTransactionManager} implementations take
* advantage of Spring lifecycle callbacks such as {@code InitializingBean} and {@code
* BeanFactoryAware}.
*/
PlatformTransactionManager annotationDrivenTransactionManager(); PlatformTransactionManager annotationDrivenTransactionManager();
} }

View File

@ -76,6 +76,9 @@
Transaction semantics such as propagation settings, the isolation level, Transaction semantics such as propagation settings, the isolation level,
the rollback rules, etc are all defined in the annotation metadata. the rollback rules, etc are all defined in the annotation metadata.
See org.springframework.transaction.annotation.EnableTransactionManagement Javadoc
for information on code-based alternatives to this XML element.
]]></xsd:documentation> ]]></xsd:documentation>
</xsd:annotation> </xsd:annotation>
<xsd:attribute name="transaction-manager" type="xsd:string" default="transactionManager"> <xsd:attribute name="transaction-manager" type="xsd:string" default="transactionManager">