Refactor ImportSelector support

Separate concerns of @Configuration class selection from the need to
register certain infrastructure beans such as auto proxy creators.

Prior to this change, ImportSelector implementations were responsible
for both of these concerns, leading to awkwardness and duplication.

Also introduced in this change is ImportBeanDefinitionRegistrar and
two implementations, AutoProxyRegistrar and AspectJAutoProxyRegistrar.
See the refactored implementations of CachingConfigurationSelector,
TransactionManagementConfigurationSelector to see the former;
AspectJAutoProxyConfigurationSelector to see the latter.

ImportSelector and ImportBeanDefinitionRegistrar are both handled as
special-case arguments to the @Import annotation within
ConfigurationClassParser.

These refactorings are important because they ensure that Spring users
will be able to understand and extend existing @Enable* annotations
and their backing ImportSelector and @Configuration classes, as well
as create their own with a minimum of effort.
This commit is contained in:
Chris Beams
2011-11-16 04:21:28 +00:00
parent 4f3cbb45f4
commit d1f6672a58
15 changed files with 311 additions and 163 deletions

View File

@@ -16,63 +16,42 @@
package org.springframework.transaction.annotation;
import java.util.Map;
import org.springframework.aop.config.AopConfigUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.AdviceMode;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportSelectorContext;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.Assert;
import org.springframework.context.annotation.AdviceModeImportSelector;
import org.springframework.context.annotation.AutoProxyRegistrar;
import org.springframework.transaction.config.TransactionManagementConfigUtils;
/**
* Selects which implementation of {@link AbstractTransactionManagementConfiguration}
* should be used based on the value of {@link EnableTransactionManagement#mode} on the
* importing @{@link Configuration} class.
* importing {@code @Configuration} class.
*
* @author Chris Beams
* @since 3.1
* @see EnableTransactionManagement
* @see AbstractTransactionManagementConfiguration
* @see ProxyTransactionManagementConfiguration
* @see org.springframework.transaction.aspectj.AspectJTransactionManagementConfiguration
* @see TransactionManagementConfigUtils#TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME
*/
public class TransactionManagementConfigurationSelector implements ImportSelector {
public class TransactionManagementConfigurationSelector
extends AdviceModeImportSelector<EnableTransactionManagement> {
/**
* {@inheritDoc}
* <p>This implementation selects {@link ProxyTransactionManagementConfiguration} if
* {@link EnableTransactionManagement#mode()} equals {@code PROXY}, and otherwise selects
* {@link org.springframework.transaction.aspectj.AspectJTransactionManagementConfiguration
* AspectJTransactionManagementConfiguration}.
* <p>If {@code #mode()} equals {@code PROXY}, an auto-proxy creator bean definition
* will also be added to the enclosing {@link BeanDefinitionRegistry} and escalated
* if necessary through the usual {@link AopConfigUtils} family of methods.
* @return {@link ProxyTransactionManagementConfiguration} or
* {@code AspectJTransactionManagementConfiguration} for {@code PROXY} and
* {@code ASPECTJ} values of {@link EnableTransactionManagement#mode()}, respectively
*/
public String[] selectImports(ImportSelectorContext context) {
AnnotationMetadata importingClassMetadata = context.getImportingClassMetadata();
BeanDefinitionRegistry registry = context.getBeanDefinitionRegistry();
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")) {
@Override
protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
if ((Boolean)enableTx.get("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
return new String[] { ProxyTransactionManagementConfiguration.class.getName() };
return new String[] { AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName() };
case ASPECTJ:
return new String[] {"org.springframework.transaction.aspectj.AspectJTransactionManagementConfiguration"};
return new String[] { TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME };
default:
throw new IllegalArgumentException("Unknown AdviceMode " + enableTx.get("mode"));
return null;
}
}
}

View File

@@ -36,4 +36,10 @@ public abstract class TransactionManagementConfigUtils {
public static final String TRANSACTION_ASPECT_CLASS_NAME =
"org.springframework.transaction.aspectj.AnnotationTransactionAspect";
/**
* The name of the AspectJ transaction management @{@code Configuration} class.
*/
public static final String TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME =
"org.springframework.transaction.aspectj.AspectJTransactionManagementConfiguration";
}