赞
踩
Springboot目前最为流行,它的约定大于配置的特性深受大家喜欢,注解驱动开发已成为主流。面向元数据遍历已经成为越来越多开发者的偏好,因此原理从Springboot的EnableTransactionManagement注解说起
表示开启事务管理
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
boolean proxyTargetClass() default false;
AdviceMode mode() default AdviceMode.PROXY;
int order() default Ordered.LOWEST_PRECEDENCE;
}
通过Import导入了TransactionManagementConfigurationSelector类,其中默认的AdviceMode为AdviceMode.PROXY,即默认使用JDK的动态代理生成代理类。
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> { /** * Returns {@link ProxyTransactionManagementConfiguration} or * {@code AspectJ(Jta)TransactionManagementConfiguration} for {@code PROXY} * and {@code ASPECTJ} values of {@link EnableTransactionManagement#mode()}, * respectively. */ @Override protected String[] selectImports(AdviceMode adviceMode) { switch (adviceMode) { //根据上面注解的默认配置,adviceMode默认为PROXY case PROXY: return new String[] { AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()}; case ASPECTJ: return new String[] { determineTransactionAspectClass()}; default: return null; } } private String determineTransactionAspectClass() { return (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader()) ? TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME : TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME); } }
TransactionManagementConfigurationSelector继承自AdviceModeImportSelector类,实现selectImports方法可以注入对应的bean,根据EnableTransactionManagement注解的默认配置,adviceMode默认为PROXY。所以这里会注入AutoProxyRegistrar和ProxyTransactionManagementConfiguration这两个类
AutoProxyRegistrar
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; // 这里面需要特别注意的是:这里是拿到所有的注解类型~~~而不是只拿@EnableAspectJAutoProxy这个类型的 // 原因:因为mode、proxyTargetClass等属性会直接影响到代理得方式,而拥有这些属性的注解至少有: // @EnableTransactionManagement、@EnableAsync、@EnableCaching等~~~~ // 甚至还有启用AOP的注解:@EnableAspectJAutoProxy它也能设置`proxyTargetClass`这个属性的值,因此也会产生关联影响~ Set<String> annTypes = importingClassMetadata.getAnnotationTypes(); for (String annType : annTypes) { AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType); if (candidate == null) { continue; } //获取mode和proxyTargetClass的属性 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) { //向容器注入的是一个InfrastructureAdvisorAutoProxyCreator,它主要是读取Advisor类,并对符合的bean进行二次代理 //如果出现多次的话,这里不是覆盖的形式,而是以第一次的为主 //当然它内部有做等级的提升之类的 AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry); //看要不要强制使用CGLIB的方式(这个属性若出现多次,是会是覆盖的形式) if ((Boolean) proxyTargetClass) { AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); return; } } } } //如果一个都没有找到则打印info日志 //可能是自己注入这个类,而不是使用注解去注入 if (!candidateFound && logger.isInfoEnabled()) { String name = getClass().getSimpleName(); logger.info(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)); } } }
主要作用就是往Spring容器注入了一个自动代理创建器:org.springframework.aop.config.internalAutoProxyCreator
,并且看看是采用CGLIB还是JDK代理
ProxyTransactionManagementConfiguration
@Configuration(proxyBeanMethods = false) public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration { @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME) @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor( TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) { BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor(); advisor.setTransactionAttributeSource(transactionAttributeSource); advisor.setAdvice(transactionInterceptor); if (this.enableTx != null) { 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( TransactionAttributeSource transactionAttributeSource) { TransactionInterceptor interceptor = new TransactionInterceptor(); interceptor.setTransactionAttributeSource(transactionAttributeSource); if (this.txManager != null) { interceptor.setTransactionManager(this.txManager); } return interceptor; } }
这里是往容器中注入事务相关的bean
MethodInterceptor
。(我们可以自定义个beanName一模一样的TransactionInterceptor来覆盖默认的事务拦截器)再看父类AbstractTransactionManagementConfiguration
@Configuration public abstract class AbstractTransactionManagementConfiguration implements ImportAware { @Nullable protected AnnotationAttributes enableTx; /** * Default transaction manager, as configured through a {@link TransactionManagementConfigurer}. */ @Nullable protected TransactionManager 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(); } //注册一个监听器工厂,用以支持@TransactionalEventListener注解标注的方法,来监听事务相关的事件 @Bean(name = TransactionManagementConfigUtils.TRANSACTIONAL_EVENT_LISTENER_FACTORY_BEAN_NAME) @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public static TransactionalEventListenerFac
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。