赞
踩
目录
1. TransactionAutoConfiguration
2. @EnableTransactionManagement
3. TransactionManagementConfigurationSelector
3.2 ProxyTransactionManagementConfiguration
3.2.1 ProxyTransactionManagementConfiguration
3.2.2 AbstractTransactionManagementConfiguration
spring boot提供的一个很好的特性就是自动配置,能够省去很多手动配置带来的烦恼,大大提升项目的开发效率;这里spring对声明式事务的支持也从自动配置说起,spring对声明式事务的原生xml支持请移步:Spring源码:声明式事务@Transactional源码分析--spring xml实现
- /**
- * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration
- * Auto-configuration} for Spring transaction.
- *
- * @author Stephane Nicoll
- * @since 1.3.0
- */
- @Configuration
- @ConditionalOnClass(PlatformTransactionManager.class)
- @AutoConfigureAfter({ JtaAutoConfiguration.class, HibernateJpaAutoConfiguration.class,
- DataSourceTransactionManagerAutoConfiguration.class,
- Neo4jDataAutoConfiguration.class })
- @EnableConfigurationProperties(TransactionProperties.class)
- public class TransactionAutoConfiguration {
-
- @Bean
- @ConditionalOnMissingBean
- public TransactionManagerCustomizers platformTransactionManagerCustomizers(
- ObjectProvider<List<PlatformTransactionManagerCustomizer<?>>> customizers) {
- return new TransactionManagerCustomizers(customizers.getIfAvailable());
- }
-
- @Configuration
- @ConditionalOnSingleCandidate(PlatformTransactionManager.class)
- public static class TransactionTemplateConfiguration {
-
- private final PlatformTransactionManager transactionManager;
-
- public TransactionTemplateConfiguration(
- PlatformTransactionManager transactionManager) {
- this.transactionManager = transactionManager;
- }
-
- @Bean
- @ConditionalOnMissingBean
- public TransactionTemplate transactionTemplate() {
- return new TransactionTemplate(this.transactionManager);
- }
-
- }
-
- @Configuration
- @ConditionalOnBean(PlatformTransactionManager.class)
- @ConditionalOnMissingBean(AbstractTransactionManagementConfiguration.class)
- public static class EnableTransactionManagementConfiguration {
-
- @Configuration
- @EnableTransactionManagement(proxyTargetClass = false)
- @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = false)
- public static class JdkDynamicAutoProxyConfiguration {
-
- }
-
- @Configuration
- @EnableTransactionManagement(proxyTargetClass = true)
- @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true)
- public static class CglibAutoProxyConfiguration {
-
- }
-
- }
- }
由于在使用spring事务管理时,spring.aop.proxy-target-class默认为true,所以CglibAutoProxyConfiguration会生效,下面分析一下@EnableTransactionManagement的处理逻辑
EnableTransactionManagement主要定义了声明式事务代理目标类的方式、增强模式以及优先级,同时通过@Import注解导入了TransactionManagementConfigurationSelector implement ImportSelector,见如下源码,下面对TransactionManagementConfigurationSelector进行分析;
- @Target(ElementType.TYPE)
- @Retention(RetentionPolicy.RUNTIME)
- @Documented
- @Import(TransactionManagementConfigurationSelector.class)
- public @interface EnableTransactionManagement {
-
- /**
- * Indicate whether subclass-based (CGLIB) proxies are to be created ({@code true}) as
- * opposed to standard Java interface-based proxies ({@code false}). The default is
- * {@code false}. <strong>Applicable only if {@link #mode()} is set to
- * {@link AdviceMode#PROXY}</strong>.
- * <p>Note that setting this attribute to {@code true} will affect <em>all</em>
- * Spring-managed beans requiring proxying, not just those marked with
- * {@code @Transactional}. For example, other beans marked with Spring's
- * {@code @Async} annotation will be upgraded to subclass proxying at the same
- * time. This approach has no negative impact in practice unless one is explicitly
- * expecting one type of proxy vs another, e.g. in tests.
- */
- boolean proxyTargetClass() default false;
-
- /**
- * Indicate how transactional advice should be applied.
- * <p><b>The default is {@link AdviceMode#PROXY}.</b>
- * Please note that proxy mode allows for interception of calls through the proxy
- * only. Local calls within the same class cannot get intercepted that way; an
- * {@link Transactional} annotation on such a method within a local call will be
- * ignored since Spring's interceptor does not even kick in for such a runtime
- * scenario. For a more advanced mode of interception, consider switching this to
- * {@link AdviceMode#ASPECTJ}.
- */
- AdviceMode mode() default AdviceMode.PROXY;
-
- /**
- * Indicate the ordering of the execution of the transaction advisor
- * when multiple advices are applied at a specific joinpoint.
- * <p>The default is {@link Ordered#LOWEST_PRECEDENCE}.
- */
- int order() default Ordered.LOWEST_PRECEDENCE;
-
- }
其继承结构如下图:
可以看出TransactionManagementConfigurationSelector本质上是一个ImportSelector,具体导入了哪些类,通过如下代码可以看出,在采用AdviceMode.PROXY时,导入了AutoProxyRegistrar和ProxyTransactionManagementConfiguration,下面分别对这两个类进行分析;
- /**
- * Selects which implementation of {@link AbstractTransactionManagementConfiguration}
- * should be used based on the value of {@link EnableTransactionManagement#mode} on the
- * importing {@code @Configuration} class.
- *
- * @author Chris Beams
- * @since 3.1
- * @see EnableTransactionManagement
- * @see ProxyTransactionManagementConfiguration
- * @see TransactionManagementConfigUtils#TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME
- */
- public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
-
- /**
- * {@inheritDoc}
- * @return {@link ProxyTransactionManagementConfiguration} or
- * {@code AspectJTransactionManagementConfiguration} for {@code PROXY} and
- * {@code ASPECTJ} values of {@link EnableTransactionManagement#mode()}, respectively
- */
- @Override
- protected String[] selectImports(AdviceMode adviceMode) {
- switch (adviceMode) {
- case PROXY:
- return new String[] {AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()};
- case ASPECTJ:
- return new String[] {TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME};
- default:
- return null;
- }
- }
-
- }
AutoProxyRegistrar的具体实现如下,通过AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry)的方式注册了beandefinition:InfrastructureAdvisorAutoProxyCreator,和spring xml声明式事务导入了同样的自动代理创建类,完成代理的创建过程;
- /**
- * Registers an auto proxy creator against the current {@link BeanDefinitionRegistry}
- * as appropriate based on an {@code @Enable*} annotation having {@code mode} and
- * {@code proxyTargetClass} attributes set to the correct values.
- *
- * @author Chris Beams
- * @since 3.1
- * @see EnableAspectJAutoProxy
- */
- public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
-
- private final Log logger = LogFactory.getLog(getClass());
-
- /**
- * Register, escalate, and configure the standard auto proxy creator (APC) against the
- * given registry. Works by finding the nearest annotation declared on the importing
- * {@code @Configuration} class that has both {@code mode} and {@code proxyTargetClass}
- * attributes. If {@code mode} is set to {@code PROXY}, the APC is registered; if
- * {@code proxyTargetClass} is set to {@code true}, then the APC is forced to use
- * subclass (CGLIB) proxying.
- * <p>Several {@code @Enable*} annotations expose both {@code mode} and
- * {@code proxyTargetClass} attributes. It is important to note that most of these
- * capabilities end up sharing a {@linkplain AopConfigUtils#AUTO_PROXY_CREATOR_BEAN_NAME
- * single APC}. For this reason, this implementation doesn't "care" exactly which
- * annotation it finds -- as long as it exposes the right {@code mode} and
- * {@code proxyTargetClass} attributes, the APC can be registered and configured all
- * the same.
- */
- @Override
- public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
- boolean candidateFound = false;
- Set<String> annoTypes = importingClassMetadata.getAnnotationTypes();
- for (String annoType : annoTypes) {
- AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annoType);
- if (candidate == null) {
- continue;
- }
- Object mode = candidate.get("mode");
- Object proxyTargetClass = candidate.get("proxyTargetClass");
- if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
- Boolean.class == proxyTargetClass.getClass()) {
- candidateFound = true;
- if (mode == AdviceMode.PROXY) {
- AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
- if ((Boolean) proxyTargetClass) {
- AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
- return;
- }
- }
- }
- }
- if (!candidateFound) {
- String name = getClass().getSimpleName();
- logger.warn(String.format("%s was imported but no annotations were found " +
- "having both 'mode' and 'proxyTargetClass' attributes of type " +
- "AdviceMode and boolean respectively. This means that auto proxy " +
- "creator registration and configuration may not have occurred as " +
- "intended, and components may not be proxied as expected. Check to " +
- "ensure that %s has been @Import'ed on the same class where these " +
- "annotations are declared; otherwise remove the import of %s " +
- "altogether.", name, name, name));
- }
- }
- }
继承结构如下:
下面分别对ProxyTransactionManagementConfiguration和AbstractTransactionManagementConfiguration进行说明;
源码如下,可见该类是一个Configuration类,完成了如下3个bean的定义:
这和spring xml声明式事务的定义完全一致;
- /**
- * {@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 {
-
- @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
- @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
- public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
- BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
- advisor.setTransactionAttributeSource(transactionAttributeSource());
- advisor.setAdvice(transactionInterceptor());
- advisor.setOrder(this.enableTx.<Integer>getNumber("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;
- }
- }
AbstractTransactionManagementConfiguration主要完成了@EnableTransactionManagement注解属性的解析,同时通过注入TransactionManagementConfigurer类型的bean,完成事务管理器PlatformTransactionManager的设置,如下:
- /**
- * Abstract base {@code @Configuration} class providing common structure for enabling
- * Spring's annotation-driven transaction management capability.
- *
- * @author Chris Beams
- * @author Stephane Nicoll
- * @since 3.1
- * @see EnableTransactionManagement
- */
- @Configuration
- public abstract class AbstractTransactionManagementConfiguration implements ImportAware {
-
- protected AnnotationAttributes enableTx;
-
- /**
- * Default transaction manager, as configured through a {@link TransactionManagementConfigurer}.
- */
- protected PlatformTransactionManager txManager;
-
-
- @Override
- public void setImportMetadata(AnnotationMetadata importMetadata) {
- this.enableTx = AnnotationAttributes.fromMap(
- importMetadata.getAnnotationAttributes(EnableTransactionManagement.class.getName(), false));
- if (this.enableTx == null) {
- throw new IllegalArgumentException(
- "@EnableTransactionManagement is not present on importing class " + importMetadata.getClassName());
- }
- }
-
- @Autowired(required = false)
- void setConfigurers(Collection<TransactionManagementConfigurer> configurers) {
- if (CollectionUtils.isEmpty(configurers)) {
- return;
- }
- if (configurers.size() > 1) {
- throw new IllegalStateException("Only one TransactionManagementConfigurer may exist");
- }
- TransactionManagementConfigurer configurer = configurers.iterator().next();
- this.txManager = configurer.annotationDrivenTransactionManager();
- }
-
-
- @Bean(name = TransactionManagementConfigUtils.TRANSACTIONAL_EVENT_LISTENER_FACTORY_BEAN_NAME)
- @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
- public TransactionalEventListenerFactory transactionalEventListenerFactory() {
- return new TransactionalEventListenerFactory();
- }
-
- }
综上,spring声明式事务xml配置形式和spring boot自动配置形式完全一致,均完成了对spring声明式事务的支持;
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。