本系列文章:
前文,我们已经完成了对注解元数据驱动的声明式事务的模拟实现,并且详细分析了模拟实现的流程和原理,下面我将带领各位来看看Spring真正的源码实现,让大家真正掌握Spring事务的精髓。
在不使用SpringBoot自动配置的情况下,开启注解元数据驱动的声明式事务有两种方式:
<tx:annotation-driven transaction-manager="transactionManager" mode="proxy" proxy-target-class="true"/>
@EnableTransactionManagement
想要进行测试,可以引入下面这段xml配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
">
<tx:annotation-driven mode="proxy" proxy-target-class="true"/>
</beans>
tx:annotation-driven标签中的mode属性和proxy-target-class属性,如果看过我上篇模拟注解驱动声明式事务的文章应该都清楚,我们自定义的注解:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(MyTransactionManagementConfigurationSelector.class)
public @interface MyEnableTransactionManagement {
/**
* 是否默认采用cglib进行代理
*/
boolean proxyTargetClass() default false;
/**
* 代理模式--是jdk,cglib代理还是aspectj代理
*/
AdviceMode mode() default AdviceMode.PROXY;
}
设置了这两个属性,目的在于能够去创建自动代理创建器,这里一样。
tx:annotation-driven不属于Spring默认命名空间,属于自定义命名空间,那么肯定存在相关的tx命名空间空间解析器,也就是下面要研究的TxNamespaceHandler :
public class TxNamespaceHandler extends NamespaceHandlerSupport {
static final String TRANSACTION_MANAGER_ATTRIBUTE = "transaction-manager";
static final String DEFAULT_TRANSACTION_MANAGER_BEAN_NAME = "transactionManager";
static String getTransactionManagerName(Element element) {
return (element.hasAttribute(TRANSACTION_MANAGER_ATTRIBUTE) ?
element.getAttribute(TRANSACTION_MANAGER_ATTRIBUTE) : DEFAULT_TRANSACTION_MANAGER_BEAN_NAME);
}
@Override
public void init() {
registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());
//annotation-driven解析器--->AnnotationDrivenBeanDefinitionParser
registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());
}
}
BeanDefinitionParserDelegate的parseCustomElement负责解析非默认命名空间的标签:
@Nullable
public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
//获取当前命令空间对应的URI,这里是http://www.springframework.org/schema/tx
String namespaceUri = getNamespaceURI(ele);
if (namespaceUri == null) {
return null;
}
//根据上面这个URI去定位到对应的自定义命名空间解析器,怎么定位的呢?
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
//如果没找到相关的解析器,那么就不管,但是会记录一个警告日志
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
//调用自定义命名空间解析器的parse方法
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
那是怎么根据一个URI定位到自定义命名空间解析器的呢?
resolve方法会通过解析URI定位到对应的自定义命名空间解析器
public NamespaceHandler resolve(String namespaceUri) {
//getHandlerMappings负责去查找所有可以发现的自定义命名空间解析器和namespaceUri的映射关系
//第一次执行该方法时,返回的是URI和对应自定义命名空间解析器的全类名,此时解析器还没有被实例化
Map<String, Object> handlerMappings = getHandlerMappings();
//找到当前namespaceUri对应的自定义命令空间解析器---没找到就返回null,找到了就尝试去实例化
Object handlerOrClassName = handlerMappings.get(namespaceUri);
if (handlerOrClassName == null) {
return null;
}
//如果是当前自定义解析器是第二次被查询,那么已经实例化了,直接返回
else if (handlerOrClassName instanceof NamespaceHandler) {
return (NamespaceHandler) handlerOrClassName;
}
//如果当前解析器第一次被使用到,那么会进行实例化
else {
String className = (String) handlerOrClassName;
try {
Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri +
"] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
}
NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
//调用实例化后的解析器的init方法
namespaceHandler.init();
//放入handlerMappings集合,这样下次来的时候,就直接返回实例化好的解析器即可
handlerMappings.put(namespaceUri, namespaceHandler);
return namespaceHandler;
}
catch (ClassNotFoundException ex) {
throw new FatalBeanException("Could not find NamespaceHandler class [" + className +
"] for namespace [" + namespaceUri + "]", ex);
}
catch (LinkageError err) {
throw new FatalBeanException("Unresolvable class definition for NamespaceHandler class [" +
className + "] for namespace [" + namespaceUri + "]", err);
}
}
}
还是那个问题: 如果获取到当前系统中可用的自定义解析器和对应URI的映射关系的呢?
这个就需要来看看getHandlerMappings的实现了:
private Map<String, Object> getHandlerMappings() {
Map<String, Object> handlerMappings = this.handlerMappings;
//如果handlerMappings 不为空,说明不是第一次来了,那么直接返回
//因为寻找当前系统中可用的自定义解析器和对应URI的映射关系,这个过程只需要执行一次即可
if (handlerMappings == null) {
synchronized (this) {
handlerMappings = this.handlerMappings;
if (handlerMappings == null) {
if (logger.isTraceEnabled()) {
logger.trace("Loading NamespaceHandler mappings from [" + this.handlerMappingsLocation + "]");
}
try {
//handlerMappingsLocation就是META-INF/spring.handlers
Properties mappings =
//这里会去类路径下找所有的META-INF/spring.handlers文件,该文件中记录了解析器和URI的映射关系
PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader);
if (logger.isTraceEnabled()) {
logger.trace("Loaded NamespaceHandler mappings: " + mappings);
}
handlerMappings = new ConcurrentHashMap<>(mappings.size());
CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings);
this.handlerMappings = handlerMappings;
}
catch (IOException ex) {
throw new IllegalStateException(
"Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", ex);
}
}
}
}
return handlerMappings;
}
这其实就是SPI思想,熟悉serviceLoader底层实现的小伙伴应该非常清楚,Drver驱动查找底层就是靠serviceLoader的服务发现机制(SPI)完成的
建议大家可以了解一下,可以看一下下面这篇文章
ServiceLoader和DriverManager的前世今生
查找到自定义命令空间解析器后,下一步就是就是调用解析器AnnotationDrivenBeanDefinitionParser的parse方法来解析自定义标签了
public BeanDefinition parse(Element element, ParserContext parserContext) {
//注册一个TransactionalEventListenerFactory--用来生产事务事件监听器的工厂---会在事务提交,回滚等时间点,回调监听器相关接口--这里不多讲
registerTransactionalEventListenerFactory(parserContext);
String mode = element.getAttribute("mode");
//判断代理模式
//如果Mode为aspectj,那么走aspectj的代理
if ("aspectj".equals(mode)) {
// mode="aspectj"
registerTransactionAspect(element, parserContext);
if (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader())) {
registerJtaTransactionAspect(element, parserContext);
}
}
//其他情况都选择jdk或者cglib代理
else {
// mode="proxy"
//下面就是准备自动代理创建器相关的东西了
//AopAutoProxyConfigurer是AnnotationDrivenBeanDefinitionParser一个内部类
AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);
}
return null;
}
AopAutoProxyConfigurer是AnnotationDrivenBeanDefinitionParser一个内部类,并且该类只有一个configureAutoProxyCreator方法
该方法主要就是来注册自动代理创建器,然后准备TransactionAttributeSource ,TransactionInterceptor和TransactionAttributeSourceAdvisor
public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {
//注册自动代理创建器,并解析标签中相关属性: proxyClass等,设置到自动代理创建器中
AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);
//默认放入容器中的事务增强器的beanName为org.springframework.transaction.config.internalTransactionAdvisor
String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;
//如果我们手动往容器中放入了与上面同名的增强器bean,那么这里就跳过,用户指定的优先级更高
if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {
Object eleSource = parserContext.extractSource(element);
// Create the TransactionAttributeSource definition.
//TransactionAttributeSource的bean定义准备
//实际放入的是AnnotationTransactionAttributeSource--他会负责解析@Transactional注解,然后形成方法和TransactionAttribute的映射关系,进行保存
RootBeanDefinition sourceDef = new RootBeanDefinition(
"org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");
sourceDef.setSource(eleSource);
//设置角色----ROLE_INFRASTRUCTURE---InfrastructureAdvisorAutoProxyCreator靠beanDefinition来过滤增强器
//这里不是增强器,仅仅表明当前注入的bean是基础设置bean
sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
//registerWithGeneratedName会注册beanDefintion到注册中心,然后返回生成的beanName
String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);
// Create the TransactionInterceptor definition.
//准备拦截器的bean定义
RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);
interceptorDef.setSource(eleSource);
//标注为基础设置bean
interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
//指定拦截器中事务管理器的beanName
registerTransactionManager(element, interceptorDef);
//指定拦截器中TransactionAttributeSource对应的beanName
interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
//注册拦截器的bean定义到注册中心,返回生成的拦截器beanName
String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);
// Create the TransactionAttributeSourceAdvisor definition.
//增强器准备--增强器类型为BeanFactoryTransactionAttributeSourceAdvisor
RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);
advisorDef.setSource(eleSource);
//标注为基础设置类--InfrastructureAdvisorAutoProxyCreator靠beanDefinition来过滤增强器
advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
//增强器需要transactionAttributeSource--因为内部的pointcut通过其来进行类级别和方法级别的过滤
advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
//指定advice--拦截器
advisorDef.getPropertyValues().add("adviceBeanName", interceptorName);
//是否指定了增强器的顺序--到时候aop过程中对筛选出来的增强器排序时会用到
if (element.hasAttribute("order")) {
advisorDef.getPropertyValues().add("order", element.getAttribute("order"));
}
//注册增强器
parserContext.getRegistry().registerBeanDefinition(txAdvisorBeanName, advisorDef);
//释放相关注册注册好的事件
CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);
compositeDef.addNestedComponent(new BeanComponentDefinition(sourceDef, sourceName));
compositeDef.addNestedComponent(new BeanComponentDefinition(interceptorDef, interceptorName));
compositeDef.addNestedComponent(new BeanComponentDefinition(advisorDef, txAdvisorBeanName));
parserContext.registerComponent(compositeDef);
}
}
}
可以看出,上面的源码思路非常清晰,和我们进行模拟的过程是一样的思路:
如果看到这里,还对TransactionAttributeSource,TransactionAdvisor,TransactionInterceptor 不熟悉的,建议先回看之前的事务管理上和中
PropertyValues在populateBean进行属性注入时,会根据PropertyValue中保存的beanName或者字面值进行属性赋值
标签中的order属性指定的是自动生成的事务增强器的advisor的order属性值,用于在筛选完后的增强器集合中进行比较排序
private static void registerTransactionManager(Element element, BeanDefinition def) {
def.getPropertyValues().add("transactionManagerBeanName",
TxNamespaceHandler.getTransactionManagerName(element));
}
这里重点是事务管理器的beanName怎么得到的:
TxNamespaceHandler.getTransactionManagerName(element)
如果我们在标签中指定了transaction-manager属性对应的值,即TransactionManager在容器中的名字,那么就会采用我们指定的,否则会去容器中寻找名字默认为transactionManagerbeanName
static String getTransactionManagerName(Element element) {
return (element.hasAttribute(TRANSACTION_MANAGER_ATTRIBUTE) ?
element.getAttribute(TRANSACTION_MANAGER_ATTRIBUTE) : DEFAULT_TRANSACTION_MANAGER_BEAN_NAME);
}
public static void registerAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {
//注册自动代理创建器,这里注册的就是InfrastructureAdvisorAutoProxyCreator
BeanDefinition beanDefinition = AopConfigUtils.registerAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
//从标签中读取出proxyClass属性,然后设置到自动代理创建器中,自动代理创建器都继承了ProxyConfig
//在创建代理对象的时候,ProxyFactory会拷贝当前自动代理创建器的ProxyConfig相关属性值
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
//释放注册bean的事件
registerComponentIfNecessary(beanDefinition, parserContext);
}
AopConfigUtils的registerAutoProxyCreatorIfNecessary过程不清楚的看下面这篇文章,这里不分析
useClassProxyingIfNecessary稍微看看:
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, @Nullable Element sourceElement) {
if (sourceElement != null) {
//标签中是否设置了proxy-target-class值
boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
//如果设置了就强迫自动代理创建器使用cglib来代理对象
if (proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
//标签中是否设置了expose-proxy属性值,如果设置了,就强迫自动代理创建器在代理对象方法被拦截时,将代理对象暴露到当前线程中去
boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
if (exposeProxy) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {
//我们已经注册过自动代理创建器了,现在注册中心一定是有对应bean定义的
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
//增强一个propertyValue
definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
}
}
//思路同上
public static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) {
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
}
}
<tx:annotation-driven mode="proxy" proxy-target-class="true"/>
tx:annotation-driven标签方式开启事务支持的流程已经走完了,还剩下一些类没进行介绍,先别急,等先讲完注解一键开启事务支持的流程后,我统一来讲,剩下待讲类有:
如果大家看过上篇文章的话,并理解了的话,下面就非常轻松了,如果没看过,强烈建议先看下:
和我们模拟时定义的注解一样:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
//导入TransactionManagementConfigurationSelector
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
//是否默认采用cglib进行代理
boolean proxyTargetClass() default false;
//代理默认
AdviceMode mode() default AdviceMode.PROXY;
//指定事务增强器的order大小
int order() default Ordered.LOWEST_PRECEDENCE;
}
TransactionManagementConfigurationSelector是EnableTransactionManagement 导入的类,该类继承了AdviceModeImportSelector
selectImports方法返回的数组中每个元素都是一个待导入到IOC中的bean的全类名
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
@Override
protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
//我们只看采用cglib和jdk动态代理的部分即可
case PROXY:
return new String[] {
//负责导入自动代理创建器--该类源码已经分析过了,不清楚的看Spring事务管理---中
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);
}
}
因为AutoProxyRegistrar源码在模拟篇中已经详细分析过了,这里我只对ProxyTransactionManagementConfiguration进行分析
该类就是对拦截器,TransactionAttributeSource 和TransactionInterceptor 进行自动注入:
@Configuration(proxyBeanMethods = false) //采用lite模式--配置类不会被代理--可以提高节约资源,提高启动效率
//指定为基础bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
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();
//设置transactionAttributeSource
advisor.setTransactionAttributeSource(transactionAttributeSource);
//设置transactionInterceptor
advisor.setAdvice(transactionInterceptor);
//是否需要设置增强器的order,enableTx来自父类,会从注解中读取order属性,判断是否被设置了
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);
//txManager来自父类
if (this.txManager != null) {
interceptor.setTransactionManager(this.txManager);
}
return interceptor;
}
}
我们再来看看这个配置类的父类吧:
@Configuration
public abstract class AbstractTransactionManagementConfiguration implements ImportAware {
@Nullable
protected AnnotationAttributes enableTx;
/**
* Default transaction manager, as configured through a {@link TransactionManagementConfigurer}.
*/
@Nullable
protected TransactionManager txManager;
//AnnotationMetadata封装着导入当前配置类的类上的注解集合的元数据信息
@Override
public void setImportMetadata(AnnotationMetadata importMetadata) {
//拿到注解元数据集合中的EnableTransactionManagement注解的属性集合
this.enableTx = AnnotationAttributes.fromMap(
importMetadata.getAnnotationAttributes(EnableTransactionManagement.class.getName()));
if (this.enableTx == null) {
throw new IllegalArgumentException(
"@EnableTransactionManagement is not present on importing class " + importMetadata.getClassName());
}
}
//TransactionManagementConfigurer中得到TransactionManager
//一般情况下这里也是没有的,springboot还没去看,但是应该会帮我们注册一个TransactionManager
//但是即使这里没有也没关系,因为事务拦截器发现自身没有设置TM时,会去找容器里面的TM
@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中的TransactionManager
TransactionManagementConfigurer configurer = configurers.iterator().next();
this.txManager = configurer.annotationDrivenTransactionManager();
}
//参考xml自定义事务驱动标签解析过程:
//注册一个TransactionalEventListenerFactory--用来生产事务事件监听器的工厂---会在事务提交,回滚等时间点,回调监听器相关接口--这里不多讲
@Bean(name = TransactionManagementConfigUtils.TRANSACTIONAL_EVENT_LISTENER_FACTORY_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public static TransactionalEventListenerFactory transactionalEventListenerFactory() {
return new TransactionalEventListenerFactory();
}
}
ImportAware接口如下:
public interface ImportAware extends Aware {
void setImportMetadata(AnnotationMetadata importMetadata);
}
该接口只有一个方法,并且该方法会在ConfigurationClassPostProcessor的内部类ImportAwareBeanPostProcessor中被调用。
具体是在ImportAwareBeanPostProcessor的postProcessBeforeInitialization方法中调用
private static class ImportAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
private final BeanFactory beanFactory;
public ImportAwareBeanPostProcessor(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
//postProcessProperties设置配置类的代理后IOC的注入问题--这里不展开
@Override
public PropertyValues postProcessProperties(@Nullable PropertyValues pvs, Object bean, String beanName) {
// Inject the BeanFactory before AutowiredAnnotationBeanPostProcessor's
// postProcessProperties method attempts to autowire other configuration beans.
if (bean instanceof EnhancedConfiguration) {
((EnhancedConfiguration) bean).setBeanFactory(this.beanFactory);
}
return pvs;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
//如果当前bean实现了ImportAware接口,就进行处理
if (bean instanceof ImportAware) {
//获取容器中的ImportRegistry注册中心
ImportRegistry ir = this.beanFactory.getBean(IMPORT_REGISTRY_BEAN_NAME, ImportRegistry.class);
AnnotationMetadata importingClass =
//如果当前bean实现了ImportAware接口,一般情况下该bean都是通过@Import注解导入的
//这里会找到是哪个类上标注了@Import注解,然后导入的该类,并拿到这个类上所有的注解元数据信息
ir.getImportingClassFor(ClassUtils.getUserClass(bean).getName());
//如果找到了,那么就调用当前类的setImportMetadata接口,否则就忽略不管
if (importingClass != null) {
((ImportAware) bean).setImportMetadata(importingClass);
}
}
return bean;
}
}
@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();
}
一般情况下TransactionManagementConfigurer在容器中是不存在的,因此transactionInterceptor关联的txManager 就为null
@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;
}
这样的话,事务拦截器在自己的invoke方法中,会去容器中寻找相关的TM,如果容器中还是没有,那就要报错了
事务拦截器工作流程不清楚的,看下面这篇文章
上面已经介绍完了两种自动开启事务支持方式的工作原理,下面来看看这其中最关键的几个没讲的类,至于已经讲过的拦截器等,这里不会再重复讲了。
AnnotationTransactionAttributeSource继承了AbstractFallbackTransactionAttributeSource,这里先来看看其父类的源码实现:
public abstract class AbstractFallbackTransactionAttributeSource
implements TransactionAttributeSource, EmbeddedValueResolverAware {
/**
* 如果当前方法不需要TransactionAttribute,即不需要事务支持,那么缓存的时候用NULL_TRANSACTION_ATTRIBUTE来表示
* 避免重复检查
*/
@SuppressWarnings("serial")
private static final TransactionAttribute NULL_TRANSACTION_ATTRIBUTE = new DefaultTransactionAttribute() {
@Override
public String toString() {
return "null";
}
};
protected final Log logger = LogFactory.getLog(getClass());
//解析SPEL表达式等
@Nullable
private transient StringValueResolver embeddedValueResolver;
/**
* 缓存
*/
private final Map<Object, TransactionAttribute> attributeCache = new ConcurrentHashMap<>(1024);
//EmbeddedValueResolverAware接口赐予的能力
@Override
public void setEmbeddedValueResolver(StringValueResolver resolver) {
this.embeddedValueResolver = resolver;
}
/**
*获取当前方法对应的TransactionAttribute信息
*/
@Override
@Nullable
public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
//忽略Object类
if (method.getDeclaringClass() == Object.class) {
return null;
}
//先查缓存
//构造缓存key
Object cacheKey = getCacheKey(method, targetClass);
TransactionAttribute cached = this.attributeCache.get(cacheKey);
if (cached != null) {
//缓存中有,还需要判断是否是NULL_TRANSACTION_ATTRIBUTE
//如果是说明当前方法不需要事务支持
if (cached == NULL_TRANSACTION_ATTRIBUTE) {
return null;
}
else {
return cached;
}
}
//缓存中没有
else {
//计算出当前方法对应的TransactionAttribute
TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
// 如果为空,说明当前方法不需要事务支持
if (txAttr == null) {
this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
}
//有,那说明需要事务支持
else {
//methodIdentification是全类名.方法名
String methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass);
if (txAttr instanceof DefaultTransactionAttribute) {
DefaultTransactionAttribute dta = (DefaultTransactionAttribute) txAttr;
//设置描述符
dta.setDescriptor(methodIdentification);
//设置解析属性时可能用到的字符串解析器
dta.resolveAttributeStrings(this.embeddedValueResolver);
}
if (logger.isTraceEnabled()) {
logger.trace("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);
}
//加入缓存
this.attributeCache.put(cacheKey, txAttr);
}
return txAttr;
}
}
protected Object getCacheKey(Method method, @Nullable Class<?> targetClass) {
return new MethodClassKey(method, targetClass);
}
//获取当前方法对应的TransactionAttribute
@Nullable
protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
// 默认只给public方法提供事务支持
//allowPublicMethodsOnly本类默认返回false,只能要重写,决定是否允许给非public方法提供事务支持
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;
}
//如果当前方法存在于一个接口上,那么我们需要该接口的实现类,并且如果targetClass是被cglib进行了代理,那么会获取该代理类的父类,然后从父类上获取到对应的method后返回
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
//判断方法上是否标注了@Transactional注解
TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
if (txAttr != null) {
return txAttr;
}
//判断类上是否有注解
txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}
//如果specificMethod和method不一致,说明targetClass是被cglib代理过后的
if (specificMethod != method) {
// Fallback is to look at the original method.
//去查看代理类的方法上是否有注解--因为可能是我们自己对目标类进行的代理
txAttr = findTransactionAttribute(method);
if (txAttr != null) {
return txAttr;
}
// Last fallback is the class of the original method.
//还是不行,再去检查代理类上是否存在注解
txAttr = findTransactionAttribute(method.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}
}
//上面都检查完了,还是没找到,说明当前方法不需要事务支持
return null;
}
/**
* Subclasses need to implement this to return the transaction attribute for the
* given class, if any.
* @param clazz the class to retrieve the attribute for
* @return all transaction attribute associated with this class, or {@code null} if none
*/
@Nullable
protected abstract TransactionAttribute findTransactionAttribute(Class<?> clazz);
/**
* Subclasses need to implement this to return the transaction attribute for the
* given method, if any.
* @param method the method to retrieve the attribute for
* @return all transaction attribute associated with this method, or {@code null} if none
*/
@Nullable
protected abstract TransactionAttribute findTransactionAttribute(Method method);
/**
* Should only public methods be allowed to have transactional semantics?
* <p>The default implementation returns {@code false}.
*/
protected boolean allowPublicMethodsOnly() {
return false;
}
}
再来看看子类的源码实现:
public class AnnotationTransactionAttributeSource extends AbstractFallbackTransactionAttributeSource
implements Serializable {
private static final boolean jta12Present;
private static final boolean ejb3Present;
static {
ClassLoader classLoader = AnnotationTransactionAttributeSource.class.getClassLoader();
jta12Present = ClassUtils.isPresent("javax.transaction.Transactional", classLoader);
ejb3Present = ClassUtils.isPresent("javax.ejb.TransactionAttribute", classLoader);
}
private final boolean publicMethodsOnly;
//注解解析器集合
private final Set<TransactionAnnotationParser> annotationParsers;
public AnnotationTransactionAttributeSource() {
this(true);
}
public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {
this.publicMethodsOnly = publicMethodsOnly;
if (jta12Present || ejb3Present) {
this.annotationParsers = new LinkedHashSet<>(4);
this.annotationParsers.add(new SpringTransactionAnnotationParser());
if (jta12Present) {
this.annotationParsers.add(new JtaTransactionAnnotationParser());
}
if (ejb3Present) {
this.annotationParsers.add(new Ejb3TransactionAnnotationParser());
}
}
else {
//解析spring自家的@Transactional注解
this.annotationParsers = Collections.singleton(new SpringTransactionAnnotationParser());
}
}
....
//当前类是否存在相关注解,即是否需要事务支持--增强器的pointcut会调用该方法进行类级别过滤
@Override
public boolean isCandidateClass(Class<?> targetClass) {
for (TransactionAnnotationParser parser : this.annotationParsers) {
//isCandidateClass当前类和当前类的方法上是否存在相关注解
if (parser.isCandidateClass(targetClass)) {
return true;
}
}
return false;
}
//判断当前类上存在注解吗,存在就解析为TransactionAttribute 返回
@Override
@Nullable
protected TransactionAttribute findTransactionAttribute(Class<?> clazz) {
return determineTransactionAttribute(clazz);
}
//判断当前方法上存在注解吗,存在就解析为TransactionAttribute 返回
@Override
@Nullable
protected TransactionAttribute findTransactionAttribute(Method method) {
return determineTransactionAttribute(method);
}
/**
利用注解解析器挨个解析,然后进行判断
*/
@Nullable
protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
for (TransactionAnnotationParser parser : this.annotationParsers) {
//解析注解,如果解析成功就直接返回
TransactionAttribute attr = parser.parseTransactionAnnotation(element);
if (attr != null) {
return attr;
}
}
return null;
}
/**
* By default, only public methods can be made transactional.
* 默认只有public方法才能有事务支持
*/
@Override
protected boolean allowPublicMethodsOnly() {
return this.publicMethodsOnly;
}
...
}
还是先看BeanFactoryTransactionAttributeSourceAdvisor的父类AbstractBeanFactoryPointcutAdvisor
public abstract class AbstractBeanFactoryPointcutAdvisor extends AbstractPointcutAdvisor implements BeanFactoryAware {
@Nullable
private String adviceBeanName;
@Nullable
private BeanFactory beanFactory;
@Nullable
private transient volatile Advice advice;
private transient volatile Object adviceMonitor = new Object();
....
//手动指定了advice
public void setAdvice(Advice advice) {
synchronized (this.adviceMonitor) {
this.advice = advice;
}
}
public void setAdviceBeanName(@Nullable String adviceBeanName) {
this.adviceBeanName = adviceBeanName;
}
//获取当前增强器内部的adivce
@Override
public Advice getAdvice() {
Advice advice = this.advice;
//如果手动指定了advice的话,这里直接返回
if (advice != null) {
return advice;
}
//如果没有手动指定的话,adviceBeanName和beanFactory必须都存在
//adviceBeanName就是我们需要手动指定的了
Assert.state(this.adviceBeanName != null, "'adviceBeanName' must be specified");
Assert.state(this.beanFactory != null, "BeanFactory must be set to resolve 'adviceBeanName'");
//会去容器中获取advice--这里为什么要加锁,感兴趣可以去深挖一下,不感兴趣的知道是从容器中获取advice即可
if (this.beanFactory.isSingleton(this.adviceBeanName)) {
// Rely on singleton semantics provided by the factory.
advice = this.beanFactory.getBean(this.adviceBeanName, Advice.class);
this.advice = advice;
return advice;
}
else {
// No singleton guarantees from the factory -> let's lock locally but
// reuse the factory's singleton lock, just in case a lazy dependency
// of our advice bean happens to trigger the singleton lock implicitly...
synchronized (this.adviceMonitor) {
advice = this.advice;
if (advice == null) {
advice = this.beanFactory.getBean(this.adviceBeanName, Advice.class);
this.advice = advice;
}
return advice;
}
}
}
....
}
再来看本类实现:
public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {
@Nullable
private TransactionAttributeSource transactionAttributeSource;
//TransactionAttributeSourcePointcut之前篇章讲过,这里不讲
private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
@Override
@Nullable
protected TransactionAttributeSource getTransactionAttributeSource() {
return transactionAttributeSource;
}
};
public void setTransactionAttributeSource(TransactionAttributeSource transactionAttributeSource) {
this.transactionAttributeSource = transactionAttributeSource;
}
public void setClassFilter(ClassFilter classFilter) {
this.pointcut.setClassFilter(classFilter);
}
@Override
public Pointcut getPointcut() {
return this.pointcut;
}
}