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.Role;
import org.springframework.transaction.annotation.AbstractTransactionManagementConfiguration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.TransactionManagementConfigurationSelector;
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
public class AspectJTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {

View File

@ -27,8 +27,8 @@ 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.
* Abstract base {@code @Configuration} class providing common structure for enabling
* Spring's annotation-driven transaction management capability.
*
* @author Chris Beams
* @since 3.1

View File

@ -26,6 +26,114 @@ import org.springframework.context.annotation.Import;
import org.springframework.context.config.AdviceMode;
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)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@ -33,11 +141,12 @@ import org.springframework.core.Ordered;
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}.
* Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
* 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}
* annotation to be defined on the concrete class. Annotations in interfaces will
* <p>Note that subclass-based proxies require the {@link Transactional @Transactional}
* 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;
@ -52,7 +161,7 @@ public @interface EnableTransactionManagement {
/**
* Indicate the ordering of the execution of the transaction advisor
* 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;
}

View File

@ -27,6 +27,15 @@ import org.springframework.transaction.interceptor.BeanFactoryTransactionAttribu
import org.springframework.transaction.interceptor.TransactionAttributeSource;
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
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.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 {
/**
* Import {@link ProxyTransactionManagementConfiguration} if {@link
* EnableTransactionManagement#mode()} equals {@code PROXY}, otherwise import {@link
* org.springframework.transaction.aspectj.AspectJTransactionManagementConfiguration
* AspectJTransactionManagementConfiguration}.
*/
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
Map<String, Object> enableTx =
importingClassMetadata.getAnnotationAttributes(EnableTransactionManagement.class.getName());

View File

@ -18,8 +18,66 @@ package org.springframework.transaction.annotation;
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 {
/**
* 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();
}

View File

@ -76,6 +76,9 @@
Transaction semantics such as propagation settings, the isolation level,
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:annotation>
<xsd:attribute name="transaction-manager" type="xsd:string" default="transactionManager">