Spring声明式事务让我们从复杂的事务处理中得到解脱,使我们再也不需要去处理获取的连接,关闭连接,事务提交和回滚操作,再也不需要在与事务相关的方法中处理大量的try…catch…finally代码,Spring中事务的使用虽然己经相对简单得多,但是,还是有很多的使用及配置规则,有兴趣的读者可以自己查阅相关资料进行深入研究,这里只列出最常用的用法。
同样,我们还是最简单的示例来进行直接的介绍。
- 准备数据库表
CREATE TABLE lz_user
(
id
bigint(20) unsigned NOT NULL AUTO_INCREMENT,
is_delete
tinyint(2) DEFAULT ‘0’,
gmt_create
datetime DEFAULT CURRENT_TIMESTAMP COMMENT ‘创建时间’,
gmt_modified
datetime DEFAULT CURRENT_TIMESTAMP,
username
varchar(32) DEFAULT NULL COMMENT ‘用户名’,
password
varchar(64) DEFAULT NULL COMMENT ‘密码’,
real_name
varchar(64) DEFAULT NULL,
manager_id
int(11) DEFAULT NULL COMMENT ‘管理员id’,
PRIMARY KEY (id
)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=‘公益口罩’;
INSERT INTO lz_user
(id
, is_delete
, gmt_create
, gmt_modified
, username
, password
, real_name
, manager_id
)
VALUES
(456,0,‘2020-05-08 10:33:57’,‘2020-05-08 10:33:57’,‘123xxxxxxxxxxxxxxxx’,‘123456’,‘xx’,1),
(457,0,‘2020-05-08 15:36:30’,‘2020-05-08 15:36:30’,‘456xxxxxxxxxxxxxxxxxxxx’,‘123456’,‘bb’,1),
(458,0,‘2020-05-08 15:37:18’,‘2020-05-08 15:37:18’,‘789xxxxxxxx’,‘123456’,‘c’,1),
(459,0,‘2020-05-08 15:38:21’,‘2020-05-08 15:38:21’,‘19884189046’,‘123456’,‘d’,1),
(460,0,‘2020-06-29 13:04:58’,‘2020-06-29 13:04:58’,‘198841890x46’,‘12345x6’,‘x1’,1),
(461,0,‘2020-06-30 15:20:24’,‘2020-06-30 15:20:24’,‘zhangsan’,‘1239832’,‘bbb’,1);
- 准备Service及Impl
public interface UserService { void updateById(User user); } public class UserServiceImpl implements UserService { private JdbcTemplate jdbcTemplate; public void setJdbcTemplate(DataSource dataSource) { this.jdbcTemplate = new JdbcTemplate(dataSource); } @Override public void updateById(User user) { jdbcTemplate.update("update lz_user set username = ? where id = ? ", new Object[]{user.getUsername(), user.getId()}); } } public interface TxService { void updateUser ( ); } public class TxServiceImpl implements TxService { private UserService userService; @Override @Transactional(propagation = Propagation.REQUIRED) public void updateUser() { User user1 = userService.selectById(456l); user1.setUsername("123"); userService.updateById(user1); int i = 0 ; int j = 0; int c = i / j ; User user2 = userService.selectById(457l); user2.setUsername("456"); userService.updateById(user2); } }
- 准备Spring配置文件spring74.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: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/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://172.16.157.238:3306/pple_test?characterEncoding=utf-8"></property> <property name="username" value="ldd_biz"></property> <property name="password" value="Hello1234"></property> <property name="initialSize" value="1"></property> <property name="maxIdle" value="2"></property> <property name="minIdle" value="1"></property> </bean> <bean id="userService" class="com.spring_1_100.test_71_80.test74_jdbc_tx_complex.UserServiceImpl"> <property name="jdbcTemplate" ref="dataSource"></property> </bean> <bean id="txService" class="com.spring_1_100.test_71_80.test74_jdbc_tx_complex.TxServiceImpl"> <property name="userService" value="#{userService}"></property> </bean> </beans>
- 测试
@Test public void updateUser() { ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:spring_1_100/config_71_80/spring74.xml"); TxService txService = (TxService) ac.getBean("txService"); txService.updateUser(); }
在上面的测试示例中,TxServiceImpl类对接口TxService中的updateUser方法中,抛出了
异常,发现用户的id=456的用户的username并没有更新为123,事务回滚,当注释掉int c = i / j;时,事务提交,此时id=456的用户username被更新为123,id为457用户的数据被更新为456。
注意
:默认情况下,Spring中的事务处理只对RuntimeException方法进行回滚,所以,如果此处将RuntimeException替换成普通的Exception不会产生回滚操作。
spring提供了声明式事务,使得我们不用关注底层的具体实现,屏蔽了多种不同的底层实现细节,为了支持多种复杂业务对事务的精细控制,spring提供了事务的传播属性,结合声明式事务,成就了一大事务利器。
在TransactionDefinition类中,spring提供了6种传播属性,接下来分别简单说明。
温馨提醒:下文提到的加入当前事务,指的是底层使用同一个Connection,但是事务状态对象是可以重新创建的,并不影响。文章提到的当前只存在一个事务,表示的是共用底层的一个Connection,而不在乎创建了多少个事务状态对象(TransactionStatus)。
- PROPAGATION_REQUIRED :说明: 如果当前已经存在事务,那么加入该事务,如果不存在事务,创建一个事务,这是默认的传播属性值。
- PROPAGATION_SUPPORTS:说明:如果当前已经存在事务,那么加入该事务,否则创建一个所谓的空事务(可以认为无事务执行)。
- PROPAGATION_MANDATORY:说明:当前必须存在一个事务,否则抛出异常。
- PROPAGATN_REQUIRES_NEW:说明:如果当前存在事务,先把当前事务相关内容封装到一个实体,然后重新创建一个新事务,接受这个实体为参数,用于事务的恢复。更直白的说法就是暂停当前事务(当前无事务则不需要),创建一个新事务。 针对这种情况,两个事务没有依赖关系,可以实现新事务回滚了,但外部事务继续执行。
- NOT_SUPPORTED:说明:如果当前存在事务,挂起当前事务,然后新的方法在没有事务的环境中执行,没有spring事务的环境下,sql的提交完全依赖于 defaultAutoCommit属性值 。
- PROPAGATION_NEVER:说明: 如果当前存在事务,则抛出异常,否则在无事务环境上执行代码。
- PROPAGATION_NESTED:说明: 如果当前存在事务,则使用 SavePoint 技术把当前事务状态进行保存,然后底层共用一个连接,当NESTED内部出错的时候,自行回滚到 SavePoint这个状态,只要外部捕获到了异常,就可以继续进行外部的事务提交,而不会受到内嵌业务的干扰,但是,如果外部事务抛出了异常,整个大事务都会回滚。
首先,我们来解析下面这一行配置。
<tx:annotation-driven transaction-manager=“transactionManager”></tx:annotation-driven>
我们知道,<tx:annotation-driven />对应的名称空间是http://www.springframework.org/schema/tx,Spring在解析标签时通过getHandlerMappings()方法加载所有META-INF/spring.handlers文件内名称空间和处理器的对应关系,存储到DefaultNamespaceHandlerResolver的handlerMappings属性中,如下图:
通过名称空间获取到处理器时,调用处理器的init方法
DefaultNamespaceHandlerResolver.java
public NamespaceHandler resolve(String namespaceUri) { Map<String, Object> handlerMappings = getHandlerMappings(); 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); namespaceHandler.init(); handlerMappings.put(namespaceUri, namespaceHandler); return namespaceHandler; } catch (ClassNotFoundException ex) { throw new FatalBeanException("NamespaceHandler class [" + className + "] for namespace [" + namespaceUri + "] not found", ex); } catch (LinkageError err) { throw new FatalBeanException("Invalid NamespaceHandler class [" + className + "] for namespace [" + namespaceUri + "]: problem with handler class file or dependent class", err); } } }
初始化名称空间所有的元素的解析器,如下
TxNamespaceHandler.java
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()); registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser()); registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser()); } }
根据TxNamespaceHandler类的init()方法,我们得知会获取到AnnotationDrivenBeanDefinitionParser类作为解析annotation-driven元素的解析器。
AnnotationDrivenBeanDefinitionParser.java
class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser { /** * Parses the {@code <tx:annotation-driven/>} tag. Will * {@link AopNamespaceUtils#registerAutoProxyCreatorIfNecessary register an AutoProxyCreator} * with the container as necessary. */ @Override public BeanDefinition parse(Element element, ParserContext parserContext) { //注册事务事件监听器,使用如例1.1 registerTransactionalEventListenerFactory(parserContext); String mode = element.getAttribute("mode"); if ("aspectj".equals(mode)) { // mode="aspectj" AspectJ方式进行事物切入 registerTransactionAspect(element, parserContext); } else { // mode="proxy" Spring Aop方式进行事物切入 AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext); } return null; } private static void registerTransactionManager(Element element, BeanDefinition def) { def.getPropertyValues().add("transactionManagerBeanName", //从元素transaction-manager中获取事务管理名称,默认为transactionManager TxNamespaceHandler.getTransactionManagerName(element)); } /** * Inner class to just introduce an AOP framework dependency when actually in proxy mode. */ private static class AopAutoProxyConfigurer { public static void configureAutoProxyCreator(Element element, ParserContext parserContext) { AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element); //TRANSACTION_ADVISOR_BEAN_NAME = "org.springframework.transaction.config.internalTransactionAdvisor" String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME; if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) { Object eleSource = parserContext.extractSource(element); // Create the TransactionAttributeSource definition. RootBeanDefinition sourceDef = new RootBeanDefinition( "org.springframework.transaction.annotation.AnnotationTransactionAttributeSource"); sourceDef.setSource(eleSource); sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef); // Create the TransactionInterceptor definition. RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class); interceptorDef.setSource(eleSource); //ROLE_INFRASTRUCTURE=2 interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); //获取事务管理器名称,并设置到TransactionInterceptor的transactionManagerBeanName属性中 registerTransactionManager(element, interceptorDef); //设置TransactionInterceptor的transactionAttributeSource属性为AnnotationTransactionAttributeSource interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName)); //注册bean,并使用Spring中定义的规则生成beanName String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef); // Create the TransactionAttributeSourceAdvisor definition. RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class); advisorDef.setSource(eleSource); //ROLE_INFRASTRUCTURE=2 advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); //设置BeanFactoryTransactionAttributeSourceAdvisor的transactionAttributeSource属性为AnnotationTransactionAttributeSource advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName)); advisorDef.getPropertyValues().add("adviceBeanName", interceptorName); //如果配置了Order属性,则将属性设置到BeanFactoryTransactionAttributeSourceAdvisor的order属性中 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); } } } }
因为Spring事务这一块本身就比较复杂,而篇幅有限,所以,今天对于mode="aspectj"的情况不做说明,只对Spring动态代理实现事务的情况做分析。
上面的代码注册了代理类及3个bean,很多的读者可能会直接略过,认为注册3个bean而己,确实这里只注册了三个bean,但是这3个bean支撑了整个事务功能,那么这三个bean是如何组织起来的呢?
首先,其中的两个bean被注册到了一个名为advisorDef的bean中,advisorDef使用BeanFactoryTransactionAttributeSourceAdvisor作为其class属性,也就是说BeanFactoryTransactionAttributeSourceAdvisor代表着当前的bean,如下图,具体代码是:
advisorDef.getPropertyValues().add(“adviceBeanName”, interceptorName);
那么如此组装的目的是什么呢?后面的代码再来分析,configureAutoProxyCreator中第一句看似很简单但却是很重要的代码:
AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);
在进入这个函数之前,来对事务监听器举个事例。
registerTransactionalEventListenerFactory(parserContext);
对于事务事件监听这一块,我相信大家用得少,但是如果我想在事务发生回滚时,打印一条日志做记录,这个时候,事件监听器就起到作用了,话不多说,先来看一个例子。
进入这个函数registerAutoProxyCreatorIfNecessary(parserContext, element);
AopNamespaceUtils.java
private void registerTransactionalEventListenerFactory(ParserContext parserContext) { RootBeanDefinition def = new RootBeanDefinition(); def.setBeanClass(TransactionalEventListenerFactory.class); //TRANSACTIONAL_EVENT_LISTENER_FACTORY_BEAN_NAME ="org.springframework.transaction.config.internalTransactionalEventListenerFactory"; parserContext.registerBeanComponent(new BeanComponentDefinition(def, TransactionManagementConfigUtils.TRANSACTIONAL_EVENT_LISTENER_FACTORY_BEAN_NAME)); }
在registerTransactionalEventListenerFactory()方法中,也没有其他事情,只是向容器中注册事件监听器工厂。
public abstract class AopNamespaceUtils { /** * The {@code proxy-target-class} attribute as found on AOP-related XML tags. */ public static final String PROXY_TARGET_CLASS_ATTRIBUTE = "proxy-target-class"; /** * The {@code expose-proxy} attribute as found on AOP-related XML tags. */ private static final String EXPOSE_PROXY_ATTRIBUTE = "expose-proxy"; public static void registerAutoProxyCreatorIfNecessary( ParserContext parserContext, Element sourceElement) { //向容器中注册AwareAdvisorAutoProxyCreator BeanDefinition beanDefinition = AopConfigUtils.registerAutoProxyCreatorIfNecessary( parserContext.getRegistry(), parserContext.extractSource(sourceElement)); useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement); registerComponentIfNecessary(beanDefinition, parserContext); } private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, Element sourceElement) { if (sourceElement != null) { boolean proxyTargetClass = Boolean.valueOf(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE)); //强制使用CGLIB代理 if (proxyTargetClass) { AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); } boolean exposeProxy = Boolean.valueOf(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE)); if (exposeProxy) { //设置expose-proxy属性为true,将代理暴露出来,使用AopContext.currentProxy()获取当前代理, //将this.b()改为((UserService)AopContext.currentProxy()).b() AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry); } } } private static void registerComponentIfNecessary(BeanDefinition beanDefinition, ParserContext parserContext) { if (beanDefinition != null) { //AUTO_PROXY_CREATOR_BEAN_NAME ="org.springframework.aop.config.internalAutoProxyCreator" //向容器中注册BeanComponentDefinition BeanComponentDefinition componentDefinition = new BeanComponentDefinition(beanDefinition, AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME); parserContext.registerComponent(componentDefinition); } } }
对于解析代码流程其实在AOP这一块的博客己经做了详细分析,上面的两个函数的主要上的是注册了InfrastructureAdvisorAutoProxyCreator类的bean,那么注册这个bean的目的是什么呢?下面来查看这个类层次结构 。
从上面的层次结构中我们可以看到,InfrastructureAdvisorAutoProxyCreator间接的实现了SmartInstantiationAwareBeanPostProcessor,而SmartInstantiationAwareBeanPostProcessor又继承了InstantiationAwareBeanPostProcessor,也就是说在Spring中,所有的bean实例化时Spring都会保证调用其postProcessAfterInitialization方法,其实现是在父类AbstractAutoProxyCreator类中实现。
AopConfigUtils.java
public abstract class AopConfigUtils { public static final String AUTO_PROXY_CREATOR_BEAN_NAME = "org.springframework.aop.config.internalAutoProxyCreator"; private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<Class<?>>(); static { APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class); APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class); APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class); } public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) { //默认使用了InfrastructureAdvisorAutoProxyCreator作为事务动态代理切点创建器 return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source); } private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) { Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); //如果容器中己经有internalAutoProxyCreator的BeanDefinition if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) { BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME); if (!cls.getName().equals(apcDefinition.getBeanClassName())) { int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName()); //获取当前类的优先级,优先级也就是在APC_PRIORITY_LIST集合中的索引位置 int requiredPriority = findPriorityForClass(cls); if (currentPriority < requiredPriority) { //如果己经存在于beanDefinition中Class的优先级小于当前cls,用当前类替换掉容器中的internalAutoProxyCreator apcDefinition.setBeanClassName(cls.getName()); } } return null; } RootBeanDefinition beanDefinition = new RootBeanDefinition(cls); beanDefinition.setSource(source); //设置order属性 beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE); beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); //注册internalAutoProxyCreator的beanDefinition registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition); return beanDefinition; } private static int findPriorityForClass(Class<?> clazz) { return APC_PRIORITY_LIST.indexOf(clazz); } private static int findPriorityForClass(String className) { for (int i = 0; i < APC_PRIORITY_LIST.size(); i++) { Class<?> clazz = APC_PRIORITY_LIST.get(i); if (clazz.getName().equals(className)) { return i; } } throw new IllegalArgumentException( "Class name [" + className + "] is not a known auto-proxy creator class"); } }
从AopConfigUtils的静态代码块中,我们得知AdvisorAutoProxyCreator优先级的先后顺序是InfrastructureAdvisorAutoProxyCreator,AspectJAwareAdvisorAutoProxyCreator,AnnotationAwareAspectJAutoProxyCreator,三个类之间的关系是怎样的呢?
从图中我们可以看出,InfrastructureAdvisorAutoProxyCreator和AspectJAwareAdvisorAutoProxyCreator都继承AbstractAdvisorAutoProxyCreator,AnnotationAwareAspectJAutoProxyCreator继承了AspectJAwareAdvisorAutoProxyCreator和AbstractAdvisorAutoProxyCreator,从代码中,我们得知,系统默认使用InfrastructureAdvisorAutoProxyCreator作为事务动态代理切点创建器,再根据类结构图可以看出InfrastructureAdvisorAutoProxyCreator是实现了BeanPostProcessor和Ordered接口的。实现这两个接口有什么用,先留悬念在这里,后面再来分析原因。
我们知道,Bean在初始化时,只要bean有BeanDefinition,将会调用applyBeanPostProcessorsAfterInitialization()方法。代码如下:
AbstractAutowireCapableBeanFactory.java
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged(new PrivilegedAction<Object>() { @Override public Object run() { invokeAwareMethods(beanName, bean); return null; } }, getAccessControlContext()); } else { invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }
applyBeanPostProcessorsAfterInitialization()方法有什么用呢?我们继续跟进代码。
AbstractAutowireCapableBeanFactory.java
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { result = beanProcessor.postProcessAfterInitialization(result, beanName); if (result == null) { return result; } } return result; }
在这个方法中,遍历所有的BeanPostProcessor,我们是不是有点似曾相识,回头看之前的代码,InfrastructureAdvisorAutoProxyCreator不就是实现了BeanPostProcessor接口嘛,为了一探究竟,我们继续跟进getBeanPostProcessors()方法。
AbstractBeanFactory.java
public List<BeanPostProcessor> getBeanPostProcessors() { return this.beanPostProcessors; }
在getBeanPostProcessors方法中,没有看到什么重要的线索,唯独发现BeanPostProcessor是从beanPostProcessors属性获取的。在AbstractBeanFactory中搜索所有的方法,发现有一个addBeanPostProcessor方法,这不正是我们要找的方法吗?我们只要在addBeanPostProcessor方法中加一个断点,就能知道beanPostProcessors属性是在哪里初始化了。
在addBeanPostProcessor方法里打断点。
发现了InfrastructureAdvisorAutoProxyCreator方法的初始化竟然在AbstractApplicationContext类的refresh方法的522行,我们将代码定位到这一行。
终于知道了是在AbstractApplicationContext的refresh方法中调用了registerBeanPostProcessors方法,其中refresh方法非常重要,这是Spring容器的基础,也是第三方代码在嵌入Spring必调的方法,最典型的就是Spring MVC,话不多说,我们要进registerBeanPostProcessors方法
PostProcessorRegistrationDelegate.java
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) { PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this); }
这个方法没有什么好说的,只是方法参数传入了Bean工厂和容器自己。
PostProcessorRegistrationDelegate.java
public static void registerBeanPostProcessors( ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) { // 1.找出所有实现BeanPostProcessor接口的类 String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false); // BeanPostProcessor的目标计数 int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length; // 2.添加BeanPostProcessorChecker(主要用于记录信息)到beanFactory中 beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount)); // 3.定义不同的变量用于区分: 实现PriorityOrdered接口的BeanPostProcessor、实现Ordered接口的BeanPostProcessor、普通BeanPostProcessor // 3.1 priorityOrderedPostProcessors: 用于存放实现PriorityOrdered接口的BeanPostProcessor ,使用 PriorityOrdered 保证顺序 List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>(); // 3.2 internalPostProcessors: 用于存放Spring内部的BeanPostProcessor List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>(); // 3.3 orderedPostProcessorNames: 用于存放实现Ordered接口的BeanPostProcessor的beanName ,使用 Ordered 保证顺序 List<String> orderedPostProcessorNames = new ArrayList<String>(); // 3.4 nonOrderedPostProcessorNames: 用于存放普通BeanPostProcessor的beanName ,无序 BeanPostProcessor List<String> nonOrderedPostProcessorNames = new ArrayList<String>(); // 4.遍历postProcessorNames, 将BeanPostProcessors按3.1 - 3.4定义的变量区分开 for (String ppName : postProcessorNames) { // 4.1 如果ppName对应的Bean实例实现了PriorityOrdered接口, 则拿到ppName对应的Bean实例并添加到priorityOrderedPostProcessors // 对于 BeanFactory 的注册,也不是直接注册就可以了,在 Spring 中支持对于 BeanPostProcessor 的排序,比如根据 PriorityOrderd // 进行排序,根据 Ordered 进行排序或者无序,而 Spring 在 BeanPostProcessor 的激活顺序的时候也会考虑对于顺序问题而先进行排序 的 // 这里可能有个地方读者还是不是很理解,对于 internalPostProcessors 中存储的后处理器也就是 MergedBeanDefinitionPostProcessor 类型的 // 处理器,在代码中似乎是被重复调用了。如: if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); priorityOrderedPostProcessors.add(pp); if (pp instanceof MergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); } } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) { orderedPostProcessorNames.add(ppName); } else { nonOrderedPostProcessorNames.add(ppName); } } // 第一步,注册所有的实现PriorityOrdered的 BeanPostProcessor sortPostProcessors(beanFactory, priorityOrderedPostProcessors); registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors); // 第二步 ,注册所有实现Ordered的BeanPostProcessor // 配合源码及注释,在 registerBeanPostProcessors 方法中所做的逻辑相信大家已经很清楚了,我们再做一些总结 // 首先,我们会发现,对于 BeanPostProcessor 的处理与 BeanFactoryPostProcessor 的处理极为相似,但是似乎又有些不一样的地方 // 经过反复的对比,我们发现,对于 BeanFactoryPostProcessor 的处理要区分两种情况,一种方式是通过硬编码的方式来处理,另一种 // 是通过配置文件的方式来处理,那么为什么在 BeanPostProcessor 的处理只考虑了配置文件的而不考虑硬编码的方式呢? // 提取了这个问题,还是因为读者没有完全理解两者实现的功能,对于 BeanFactoryPostProcessor 的处理,不但要实现注册的功能, // 而且还要实现对后处理器的激活操作,所以需要载入配置的定义,并进行激活,而对于 BeanPostProcessor 并不需要马上调用,再说 // 硬编码的方式实现功能只需要将配置文件的 BeanPostProcessor 提取出来并注册进入 beanFactory 就可以了 List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>(); for (String ppName : orderedPostProcessorNames) { BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); orderedPostProcessors.add(pp); if (pp instanceof MergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); } } sortPostProcessors(beanFactory, orderedPostProcessors); registerBeanPostProcessors(beanFactory, orderedPostProcessors); // 第三步,注册所有无序的 BeanPostProcessor List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>(); for (String ppName : nonOrderedPostProcessorNames) { BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); nonOrderedPostProcessors.add(pp); if (pp instanceof MergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); } } registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors); // 第四步,注册所有 MergedBeanDefinitionPostProcessor 类型的 BeanPostProcessor ,并非重复注册 sortPostProcessors(beanFactory, internalPostProcessors); registerBeanPostProcessors(beanFactory, internalPostProcessors); beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext)); }
经过上面这段代码的分析,我相信大家应该理解了,首先调用beanFactory的getBeanNamesForType方法,获取容器中所有实现BeanPostProcessor的beanName,这里肯定能找到InfrastructureAdvisorAutoProxyCreator的beanName,遍历所有的beanNames,因为InfrastructureAdvisorAutoProxyCreator实现了Ordered接口,因此被加入到orderedPostProcessorNames,再调用registerBeanPostProcessors方法,注册所有的orderedPostProcessorNames,下面我们再跟进registerBeanPostProcessors方法。
PostProcessorRegistrationDelegate.java
private static void registerBeanPostProcessors( ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) { for (BeanPostProcessor postProcessor : postProcessors) { beanFactory.addBeanPostProcessor(postProcessor); } }
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) { Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null"); //先移除掉beanPostProcessor属性 this.beanPostProcessors.remove(beanPostProcessor); //再添加beanPostProcessor属性 this.beanPostProcessors.add(beanPostProcessor); if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) { this.hasInstantiationAwareBeanPostProcessors = true; } if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) { this.hasDestructionAwareBeanPostProcessors = true; } }
通过上面方法分析,我们终于知道了getBeanPostProcessors方法中beanPostProcessors属性的由来,由容器调用其registerBeanPostProcessors方法,找出容器中所有实现了BeanPostProcessor接口的beanName,然后所有的beanName加入到AbstractBeanFactory工厂的beanPostProcessors属性中。
我们再次回到刚刚分析的
postProcessAfterInitialization方法,此时从beanPostProcessors获取到InfrastructureAdvisorAutoProxyCreator类,调用其postProcessAfterInitialization方法。
AbstractAutoProxyCreator.java
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean != null) { //根据给定的bean的class和name构建出key,beanClassName_beanName Object cacheKey = getCacheKey(bean.getClass(), beanName); //是否是由于避免循环依赖而创建的bean的代理 if (!this.earlyProxyReferences.contains(cacheKey)) { return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; }
这里实现的主要上的是对指定的bean进行代理,当然首先要确定是否需要代理,检测的工作都委托给了wrapIfNecessary函数进行。
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { //排除掉不需要代理的类 if (beanName != null && this.targetSourcedBeans.contains(beanName)) { return bean; } if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } //给定的bean类是否代表一个基础设施类,不应该被代理,或者配置了指定的bean不需要自动代理 if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } //获取代理切点的拦截器 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); if (specificInterceptors != DO_NOT_PROXY) { this.advisedBeans.put(cacheKey, Boolean.TRUE); //创建动态代理 Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; }
wrapIfNecessary函数的功能实现起来很复杂,但是逻辑上理解起来还是相对简单的,在wrapIfNecessary函数中主要工作如下:
- 找出指定的bean对应的增强器
- 根据找出的增强器创建代理 。
听起来似乎简单的逻辑,Spring中又做了哪些复杂的工作呢?对于创建代理部分,通过之前的分析相信大家己经很熟悉了,但是对于增强器的获取,Spring又是如何做的呢?
代码运行到这里,不要被代码绕晕了,此时的bean是当前创建的bean,而不是刚刚我们找到的InfrastructureAdvisorAutoProxyCreator,而我们要为之创建代理的也是当前初始化的bean,如UserServiceImpl。下面就开始来判断UserServiceImpl需不需要动态创建代理了,需不需要创建代理,就看UserServiceImpl中的方法有没有切面拦截。
获取对应的class/method的增强器
获取指定的bean对应的增强器,其中包含两个关键字,增强器与对应,也就是说,在getAdvicesAndAdvisorsForBean函数中,不但要找到增强器,而且还需要判断增强器是否满足要求。
AbstractAdvisorAutoProxyCreator.java
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) { List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName); if (advisors.isEmpty()) { return DO_NOT_PROXY; } return advisors.toArray(); }
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { //获取容器中所有切面 List<Advisor> candidateAdvisors = findCandidateAdvisors(); //获取容器中对bean方法拦截的所有切面 List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); extendAdvisors(eligibleAdvisors); if (!eligibleAdvisors.isEmpty()) { eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; }
其实我们也渐渐的体会到Spring中代码的优秀,即使一个很复杂的逻辑,在Spring中也会被拆分成若干个小的逻辑,然后在每个函数中实现,使得每个函数的逻辑简单到我们能快速理解,而不会像有些人开发的那样,将一大堆的逻辑都罗列在一个函数中,给后期维护人员造成巨大的困扰。
同样通过上面的函数,Spring又将在任务进行任务进行拆分,分成了获取所有的增强器与增强器是否匹配两个功能点。
带着好奇,Spring是如何获取到所有切面的呢?我们来看看findCandidateAdvisors方法的内部实现。
1. 寻找候选增强器
在findCandidateAdvisors函数中完成的就是获取增强器的功能。
BeanFactoryAdvisorRetrievalHelper.java
public List<Advisor> findCandidateAdvisors() { String[] advisorNames = null; synchronized (this) { advisorNames = this.cachedAdvisorBeanNames; //从bean工厂中获取所有实现了Advisor接口的通知器名称 if (advisorNames == null) { advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory, Advisor.class, true, false); this.cachedAdvisorBeanNames = advisorNames; } } if (advisorNames.length == 0) { return new LinkedList<Advisor>(); } List<Advisor> advisors = new LinkedList<Advisor>(); for (String name : advisorNames) { if (isEligibleBean(name)) { if (this.beanFactory.isCurrentlyInCreation(name)) { if (logger.isDebugEnabled()) { logger.debug("Skipping currently created advisor '" + name + "'"); } } else { try { advisors.add(this.beanFactory.getBean(name, Advisor.class)); } catch (BeanCreationException ex) { Throwable rootCause = ex.getMostSpecificCause(); if (rootCause instanceof BeanCurrentlyInCreationException) { BeanCreationException bce = (BeanCreationException) rootCause; if (this.beanFactory.isCurrentlyInCreation(bce.getBeanName())) { if (logger.isDebugEnabled()) { logger.debug("Skipping advisor '" + name + "' with dependency on currently created bean: " + ex.getMessage()); } // Ignore: indicates a reference back to the bean we're trying to advise. // We want to find advisors other than the currently created bean itself. continue; } } throw ex; } } } } return advisors; }
对于上面的函数,你看懂其中的奥妙了吗?首先是通过BeanFactoryUtils类提供的工具方法获取所有的对应的Advisor.class类,获取办法无非是使用ListableBeanFactory提供的方法:
String[] getBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit);
而当我们知道增强器在容器中的beanName时,获取增强器己经不是问题了,在BeanFactory提供了这样的方法,可以帮助我们快速的定位对应的bean实例。
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
上图中我们可以看到org.springframework.transaction.config.internalTransactionAdvisor,这个不是似曾相识吗?回想一下,internalTransactionAdvisor不就是我们在解析<tx:annotation-driven/>标签时在configureAutoProxyCreator方法中注册的BeanFactoryTransactionAttributeSourceAdvisor嘛,因为BeanFactoryTransactionAttributeSourceAdvisor同样实现了Advisor接口,那么在获取所有的增强器时自然也会将此bean提取出来,并随着其他的增强器一起在后续的步骤中被织入代理,我们继续跟进findAdvisorsThatCanApply方法。
2. 候选增强器寻找到匹配项
当找出对应的增强器后,接下来的任务就是看这些增强器是否与对应的class匹配了,当然不只是class,class内的方法如果匹配也可以通过验证。
AbstractAdvisorAutoProxyCreator.java
protected List<Advisor> findAdvisorsThatCanApply( List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) { ProxyCreationContext.setCurrentProxiedBeanName(beanName); try { return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass); } finally { ProxyCreationContext.setCurrentProxiedBeanName(null); } }
AopUtils.java
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) { if (candidateAdvisors.isEmpty()) { return candidateAdvisors; } List<Advisor> eligibleAdvisors = new LinkedList<Advisor>(); //引介增强处理,BeanFactoryTransactionAttributeSourceAdvisor当然不是引介通知器 for (Advisor candidate : candidateAdvisors) { if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) { eligibleAdvisors.add(candidate); } } boolean hasIntroductions = !eligibleAdvisors.isEmpty(); for (Advisor candidate : candidateAdvisors) { if (candidate instanceof IntroductionAdvisor) { //过滤到引介增强 continue; } //判断通知器是否对当前类或方法进行增强 if (canApply(candidate, clazz, hasIntroductions)) { eligibleAdvisors.add(candidate); } } return eligibleAdvisors; }
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) { if (advisor instanceof IntroductionAdvisor) { return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass); } else if (advisor instanceof PointcutAdvisor) { PointcutAdvisor pca = (PointcutAdvisor) advisor; return canApply(pca.getPointcut(), targetClass, hasIntroductions); } else { return true; } }
当前我们分析的是对于UserService是否适用于此增强方法,那么当前的advisor就是之前找出来的类型为BeanFactoryTransactionAttributeSourceAdvisor的bean的实例,而通过类的层次结构我们又知道:BeanFactoryTransactionAttributeSourceAdvisor间接的实现了PointCutAdvisor,因此,在canApply函数中的if判断时就会通过判断,会将BeanFactoryTransactionAttributeSourceAdvisor中的getPointcut()方法返回值作为参数继续调用canApply方法,而getPoint方法返回的是TransactionAttributeSourcePointcut类型的实例,对于transactionAttributeSource这个属性大家应该还有印象吧?在解析自定义标签的时候注入进去的。
BeanFactoryTransactionAttributeSourceAdvisor.java
public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor { private TransactionAttributeSource transactionAttributeSource; private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() { @Override protected TransactionAttributeSource getTransactionAttributeSource() { return transactionAttributeSource; } }; //在构建BeanFactoryTransactionAttributeSourceAdvisor实例时,将AnnotationTransactionAttributeSource对象注入 public void setTransactionAttributeSource(TransactionAttributeSource transactionAttributeSource) { this.transactionAttributeSource = transactionAttributeSource; } public void setClassFilter(ClassFilter classFilter) { this.pointcut.setClassFilter(classFilter); } @Override public Pointcut getPointcut() { return this.pointcut; } }
通过上述方法,我们知道在canApply()方法中的第一个参数是TransactionAttributeSourcePointcut,我们继续探索canApply方法。
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) { Assert.notNull(pc, "Pointcut must not be null"); if (!pc.getClassFilter().matches(targetClass)) { return false; } //此时的pc是TransactionAttributeSourcePointcut //此时pc.getMethodMatcher()返回的正是自身(this) MethodMatcher methodMatcher = pc.getMethodMatcher(); IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null; //引介增强处理 if (methodMatcher instanceof IntroductionAwareMethodMatcher) { introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher; } //获取目标类以及目标类实现的所有接口 Set<Class<?>> classes = new LinkedHashSet<Class<?>>(ClassUtils.getAllInterfacesForClassAsSet(targetClass)); classes.add(targetClass); for (Class<?> clazz : classes) { Method[] methods = clazz.getMethods(); //获取目标类以及目标类实现的所有接口 for (Method method : methods) { if ((introductionAwareMethodMatcher != null && introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) || methodMatcher.matches(method, targetClass)) { return true; } } } return false; }
从上图中我们可以看出,TransactionAttributeSourcePointcut是继承StaticMethodMatcherPointcut类,TransactionAttributeSourcePointcut本身没有实现getMethodMatcher方法,因此point调用getMethodMatcher方法时是调用StaticMethodMatcherPointcut中的getMethodMatcher方法,返回的正是自身TransactionAttributeSourcePointcut。
StaticMethodMatcherPointcut.java
public final MethodMatcher getMethodMatcher() { return this; }
通过上面的函数大致理清大体的脉络,首先获取对应的类的所有接口并连同类本身一起遍历,遍历的过程中又对类中的方法再次遍历,一旦匹配成功便认为这个类适用于当前增强器。
到这里我们不禁想问?对于事务的配置不仅仅局限于在函数中配置,我们都知道,在类活接口上的配置可以延续到类中的每个函数,那么,如果针对每个函数进行检测,在类本身上配置的事务属性岂不是检测不到了吗?带着这个疑问,我们继续探求matcher方法。
从StaticMethodMatcherPointcut中得知,getMethodMatcher返回的是TransactionAttributeSourcePointcut对象本身。紧接着,我们来看matches方法。
TransactionAttributeSourcePointcut.java
abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable { @Override public boolean matches(Method method, Class<?> targetClass) { //过滤掉TransactionalProxy类及其子类 if (TransactionalProxy.class.isAssignableFrom(targetClass)) { return false; } //自定义标签解析时注入,调用子类获取到AnnotationTransactionAttributeSource TransactionAttributeSource tas = getTransactionAttributeSource(); return (tas == null || tas.getTransactionAttribute(method, targetClass) != null); } protected abstract TransactionAttributeSource getTransactionAttributeSource(); }
我们知道当前TransactionAttributeSourcePointcut对像是BeanFactoryTransactionAttributeSourceAdvisor对象中的point属性,因此getTransactionAttributeSource()方法是调用BeanFactoryTransactionAttributeSourceAdvisor对象中的pointcut对象的getTransactionAttributeSource方法,getTransactionAttributeSource方法返回的是对象本身属性transactionAttributeSource,这个属性的赋值在解析<tx:annotation-driven />标签时己经被交给了Spring来管理。【transactionAttributeSource在AopAutoProxyConfigurer类的configureAutoProxyCreator方法中交给了Spring管理】,Spring在构建BeanFactoryTransactionAttributeSourceAdvisor对象时会自动将AnnotationTransactionAttributeSource对象注入到transactionAttributeSource属性中。再来看getTransactionAttribute方法。
AbstractFallbackTransactionAttributeSource.java
public TransactionAttribute getTransactionAttribute(Method method, Class<?> targetClass) { // 缓存处理 Object cacheKey = getCacheKey(method, targetClass); Object cached = this.attributeCache.get(cacheKey); if (cached != null) { // Value will either be canonical value indicating there is no transaction attribute, // or an actual transaction attribute. if (cached == NULL_TRANSACTION_ATTRIBUTE) { return null; } else { return (TransactionAttribute) cached; } } else { //真正的去获取事务属性 TransactionAttribute txAtt = computeTransactionAttribute(method, targetClass); // Put it in the cache. if (txAtt == null) { this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE); } else { if (logger.isDebugEnabled()) { Class<?> classToLog = (targetClass != null ? targetClass : method.getDeclaringClass()); logger.debug("Adding transactional method '" + classToLog.getSimpleName() + "." + method.getName() + "' with attribute: " + txAtt); } this.attributeCache.put(cacheKey, txAtt); } return txAtt; } }
很遗憾,在getTransactionAttribute函数中并没有找到我们想要的代码,这里是指常规的一贯的套路,尝试从缓存中加载,如果对应的信息没有被缓存的话,工作又委托给了 computeTransactionAttribute函数,在 computeTransactionAttribute函数中终于看到了事务标签的提取过程。
为什么会调用AbstractFallbackTransactionAttributeSource中的getTransactionAttribute方法呢?我们来看看AnnotationTransactionAttributeSource类的对象关系。
原来如此,AnnotationTransactionAttributeSource没有实现getTransactionAttribute方法,只能调用父类的getTransactionAttribute方法。
AbstractFallbackTransactionAttributeSource.java
protected TransactionAttribute computeTransactionAttribute(Method method, Class<?> targetClass) { //方法必需是public方法 if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) { return null; } //过滤到CGLIB方法 Class<?> userClass = ClassUtils.getUserClass(targetClass); //对于接口方法的处理,method代表接口中的方法,specificMethod代表实现类的方法 Method specificMethod = ClassUtils.getMostSpecificMethod(method, userClass); //如果是桥接方法,或者说是泛型方法处理 specificMethod = BridgeMethodResolver.findBridgedMethod(specificMethod); //真实方法事务属性获取 TransactionAttribute txAtt = findTransactionAttribute(specificMethod); if (txAtt != null) { return txAtt; } //真实方法所在类事务属性获取 txAtt = findTransactionAttribute(specificMethod.getDeclaringClass()); if (txAtt != null) { return txAtt; } if (specificMethod != method) { //原方法事务属性获取 txAtt = findTransactionAttribute(method); if (txAtt != null) { return txAtt; } //原方法所在类事务属性获取 return findTransactionAttribute(method.getDeclaringClass()); } return null; }
对于这个方法的理解,我们先来弄清楚真实方法和原方法是什么?如AService接口中有一个接口方法updateA,AServiceImpl实现了AService接口,并实现了AService接口中的updateA方法,那么computeTransactionAttribute方法传入Method为原来方法,如果computeTransactionAttribute方法传入的是AService接口中的updateA方法,那么真实方法是AServiceImpl的updateA方法,以@Transactional注解为例,那么事务属性的查找顺序先在AServiceImpl的updateA查找有没有@Transactional,如果没有,再到AServiceImpl类中查找,再找不到,则到AService中的updateA查找,还找不到,则到AService接口中查找。都找不到的情况,返回null,总结一下接口查找事务属性的先后顺序:
AServiceImpl.updateA->AServiceImpl->AService.updateA->AService。
对于事务属性的获取规则相信大家都己经很清楚,如果方法中存在事务属性,则使用方法上的属性,否则使用方法所在类上的属性,如果方法所有类的属性上还是没有搜寻到对应的事务属性,那么再搜寻接口中的方法,再没有的话,最后尝试搜寻接口所在类上面的声明,对于computeTransactionAttribute中的逻辑与我们所认识的规则并无差别,但是上面的函数中并没有真正的去搜寻事务属性的逻辑,而是搭建了个执行构架,将搜寻事务的属性的任务委托给了findTransactionAttribute方法去执行。
AnnotationTransactionAttributeSource.java
protected TransactionAttribute findTransactionAttribute(Method method) { return determineTransactionAttribute(method); } protected TransactionAttribute determineTransactionAttribute(Class<?> clazz) { return determineTransactionAttribute(clazz); }
protected TransactionAttribute determineTransactionAttribute(AnnotatedElement ae) { //遍历annotationParsers集合 for (TransactionAnnotationParser annotationParser : this.annotationParsers) { TransactionAttribute attr = annotationParser.parseTransactionAnnotation(ae); if (attr != null) { return attr; } } return null; }
关于annotationParsers集合中数据是怎样来的呢?我们来看看AnnotationTransactionAttributeSource的实例化,如果没有jta或ejb的使用,默认是使用SpringTransactionAnnotationParser解析器。
public AnnotationTransactionAttributeSource() { this(true); } public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) { this.publicMethodsOnly = publicMethodsOnly; this.annotationParsers = new LinkedHashSet<TransactionAnnotationParser>(2); this.annotationParsers.add(new SpringTransactionAnnotationParser()); if (jta12Present) { this.annotationParsers.add(new JtaTransactionAnnotationParser()); } if (ejb3Present) { this.annotationParsers.add(new Ejb3TransactionAnnotationParser()); } }
至此,我们终于看到了想看到的获取注解标记的代码,首先会判断当前的来中是否含有Transactionnal注解,这是事务属性的基础,当然如果有的话会继续调用parseTransactionAnnotation方法解析详细的属性。
SpringTransactionAnnotationParser.java
public class SpringTransactionAnnotationParser implements TransactionAnnotationParser, Serializable { @Override public TransactionAttribute parseTransactionAnnotation(AnnotatedElement ae) { //获取类或方法中的Transactional注解 AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ae, Transactional.class); if (attributes != null) { //解析Transactional注解 return parseTransactionAnnotation(attributes); } else { return null; } } protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) { RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute(); //获取Transactional注解中的属性propagation | isolation | timeout | readOnly,value | rollbackFor | rollbackForClassName | noRollbackFor | noRollbackForClassName //返回TransactionAttribute Propagation propagation = attributes.getEnum("propagation"); rbta.setPropagationBehavior(propagation.value()); Isolation isolation = attributes.getEnum("isolation"); rbta.setIsolationLevel(isolation.value()); rbta.setTimeout(attributes.getNumber("timeout").intValue()); rbta.setReadOnly(attributes.getBoolean("readOnly")); rbta.setQualifier(attributes.getString("value")); ArrayList<RollbackRuleAttribute> rollBackRules = new ArrayList<RollbackRuleAttribute>(); Class<?>[] rbf = attributes.getClassArray("rollbackFor"); for (Class<?> rbRule : rbf) { RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule); rollBackRules.add(rule); } String[] rbfc = attributes.getStringArray("rollbackForClassName"); for (String rbRule : rbfc) { RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule); rollBackRules.add(rule); } Class<?>[] nrbf = attributes.getClassArray("noRollbackFor"); for (Class<?> rbRule : nrbf) { NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule); rollBackRules.add(rule); } String[] nrbfc = attributes.getStringArray("noRollbackForClassName"); for (String rbRule : nrbfc) { NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule); rollBackRules.add(rule); } rbta.getRollbackRules().addAll(rollBackRules); return rbta; } }
如果返回的TransactionAttribute不为空,或者说方法或方法所在类或方法的接口方法或方法的接口配置了@Transactional注解,则说明matches返回true。匹配成功,将使用JDK动态代理。
上面方法中实现了对类或者方法的事务属性的解析,你会在这个类中看到任何你常用或不常用的属性提取。
至此,我们终于完成了事务标签的解析,我们是不是分析得太远了,似乎忘记了从哪里开始了,再回顾一下,我们的现在的任务是找出某个增强器是否适合对应的类,而是否匹配的关键则是在于是否从指定的类或类中的方法中找到对应的事务属性,现在,我们以UserServiceImpl为例,己经在其他的接口UserService中找到了事务属性,所以,它是与事务增强器匹配的,也就是它会被事务功能修饰。
至此,事务功能的初始化工作便己经结束了,当判断某个bean适用于事务增强时,也就是适用于增强器BeanFactoryTransactionAttributeSourceAdvisor,没错,还是这个类,所以说,在自定义标签解析时,注入的类成为整个事务功能的基础。
BeanFactoryTransactionAttributeSourceAdvisor作为Advisor的实现类,自然要遵从Advisor的处理方式,当代理被调用笔时会调用这个类的增强方法,也就是bean的Advise,又因为在解析事务定义的标签时我们把TransactionInterceptor类型的bean注入到BeanFactoryTransactionAttributeSourceAdvisor中,所以在调用事务增强器增强的代理类时会首先执行TransactionInterceptor进行增强,同时,也就是在TransactionInterceptor类中的invoke方法中完成整个事务的逻辑。
AbstractAutoProxyCreator.java
protected Object createProxy( Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) { ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.copyFrom(this); //如果没有配置proxy-target-class="true",则是基于接口进行代理,也就是使用JDK动态代理 if (!proxyFactory.isProxyTargetClass()) { //如果当前beanFactory instanceof ConfigurableListableBeanFactory // && beanName对应的BeanDefinition中的preserveTargetClass属性为true if (shouldProxyTargetClass(beanClass, beanName)) { //还是使用cglib代理 proxyFactory.setProxyTargetClass(true); } else { //使用JDK动态代理,将beanClass的所有接口将入到proxyFactory的interfaces接口中 evaluateProxyInterfaces(beanClass, proxyFactory); } } //将commonInterceptors和specificInterceptors合并返回 Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); for (Advisor advisor : advisors) { proxyFactory.addAdvisor(advisor); } proxyFactory.setTargetSource(targetSource); //处理用户定制代理工厂 customizeProxyFactory(proxyFactory); proxyFactory.setFrozen(this.freezeProxy); if (advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } return proxyFactory.getProxy(getProxyClassLoader()); }
ProxyFactory.java
public Object getProxy(ClassLoader classLoader) { //创建AOP代理代理工厂,再获取代理 return createAopProxy().getProxy(classLoader); }
ProxyCreatorSupport.java
protected final synchronized AopProxy createAopProxy() { if (!this.active) { activate(); } //默认是获取DefaultAopProxyFactory代理工厂 return getAopProxyFactory().createAopProxy(this); }
DefaultAopProxyFactory.java
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { //optimize : 如果将此属性设置为true,将强制使用CGlib动态代理技术 //如: // <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator" // p:beanNames="*er" // p:interceptorNames="greetingAdvisor" // p:optimize="true"></bean> //或: // <aop:config proxy-target-class="true" ... /> //或 //代理工厂的除SpringProxy接口外的interfaces为0 //则使用CGLIB代理 if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class<?> targetClass = config.getTargetClass(); if (targetClass == null) { throw new AopConfigException("TargetSource cannot determine target class: " + "Either an interface or a target is required for proxy creation."); } //如果目标类是接口或者是代理类,则使用CGLIB代理 if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); } return new ObjenesisCglibAopProxy(config); } //否则使用JDK动态代理 else { return new JdkDynamicAopProxy(config); } }
JdkDynamicAopProxy.java
public Object getProxy(ClassLoader classLoader) { if (logger.isDebugEnabled()) { logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource()); } //将目标类的接口和SpringProxy及Advised合并 Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised); //如果目标类有equals方法,则设置JdkDynamicAopProxy.equalsDefined=true //如果目标类有hashCode方法,则设置JdkDynamicAopProxy.hashCodeDefined=true findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); //创建jdk动态代理 return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); }
程序执行到这里,基于接口的jdk动态代理己经创建完成,也就是此时保存到Spring容器的实例不再是原来的TxServiceImpl实例,而是基于TxServiceImpl的动态代理类。接下来我们继续来分析Spring事务相关源码。
JdkDynamicAopProxy.java
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { MethodInvocation invocation; Object oldProxy = null; boolean setProxyContext = false; TargetSource targetSource = this.advised.targetSource; Class<?> targetClass = null; Object target = null; try { //如果接口中没有定义equals方法并且当前被调用的方法是equals方法,不使用代理 if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { return equals(args[0]); } //如果接口中没有定义hashCode方法并且当前被调用的方法是hashCode方法,不使用代理 if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { return hashCode(); } //该属性用于空值生成的代理对象是否可以强制转型为Advised,默认值为false, //表示任何生成的代理对象都可以强制转换成Advised,true是不可以,可以通过Adviced查询代理对象的一些状态 if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) { return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); } Object retVal; // 标记代理对象是否应该被aop框架通过AopContext以ThreadLocal的形式暴露出去。 // 当一个代理对象需要调用它自己的另外一个代理方法时,这个属性将非常有用。默认是是false,以避免不必要的拦截。 if (this.advised.exposeProxy) { oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } //获取目标类 target = targetSource.getTarget(); if (target != null) { targetClass = target.getClass(); } //获取拦截器链 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); //如果拦截器链为空,反射调用,并避免创建MethodInvocation if (chain.isEmpty()) { //我们可以跳过创建MethodInvocation的操作:直接直接调用目标 //注意,最终的调用者必须是InvokerInterceptor,所以我们知道它 //除了对目标执行反射操作外,不执行任何操作,并且不进行热交换或奇特代理。 retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args); } else { //创建反射方法调用 invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); //调用拦截器链 retVal = invocation.proceed(); } Class<?> returnType = method.getReturnType(); if (retVal != null && retVal == target && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { //方法返回this处理 retVal = proxy; } //返回值为null,但是返回值类型是基本数据类型(int,double),则抛出异常 else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) { throw new AopInvocationException( "Null return value from advice does not match primitive return type for: " + method); } return retVal; } finally { if (target != null && !targetSource.isStatic()) { targetSource.releaseTarget(target); } if (setProxyContext) { //恢复旧的代理 AopContext.setCurrentProxy(oldProxy); } } }
DefaultAdvisorChainFactory.java
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class<?> targetClass) { MethodCacheKey cacheKey = new MethodCacheKey(method); List<Object> cached = this.methodCache.get(cacheKey); if (cached == null) { cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice( this, method, targetClass); this.methodCache.put(cacheKey, cached); } return cached; }
public List<Object> getInterceptorsAndDynamicInterceptionAdvice( Advised config, Method method, Class<?> targetClass) { List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length); Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass()); boolean hasIntroductions = hasMatchingIntroductions(config, actualClass); AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance(); //遍历所有的通知器 for (Advisor advisor : config.getAdvisors()) { if (advisor instanceof PointcutAdvisor) { PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor; if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) { //获取通知器对应的所有拦截器 MethodInterceptor[] interceptors = registry.getInterceptors(advisor); MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher(); if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) { if (mm.isRuntime()) { for (MethodInterceptor interceptor : interceptors) { interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm)); } } else { interceptorList.addAll(Arrays.asList(interceptors)); } } } } else if (advisor instanceof IntroductionAdvisor) { IntroductionAdvisor ia = (IntroductionAdvisor) advisor; if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) { Interceptor[] interceptors = registry.getInterceptors(advisor); interceptorList.addAll(Arrays.asList(interceptors)); } } else { Interceptor[] interceptors = registry.getInterceptors(advisor); interceptorList.addAll(Arrays.asList(interceptors)); } } return interceptorList; }
DefaultAdvisorAdapterRegistry.java
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException { List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(3); //获取通知器对应的拦截器 Advice advice = advisor.getAdvice(); if (advice instanceof MethodInterceptor) { interceptors.add((MethodInterceptor) advice); } for (AdvisorAdapter adapter : this.adapters) { if (adapter.supportsAdvice(advice)) { interceptors.add(adapter.getInterceptor(advisor)); } } if (interceptors.isEmpty()) { throw new UnknownAdviceTypeException(advisor.getAdvice()); } return interceptors.toArray(new MethodInterceptor[interceptors.size()]); }
AbstractBeanFactoryPointcutAdvisor.java
public Advice getAdvice() { synchronized (this.adviceMonitor) { if (this.advice == null && this.adviceBeanName != null) { Assert.state(this.beanFactory != null, "BeanFactory must be set to resolve 'adviceBeanName'"); this.advice = this.beanFactory.getBean(this.adviceBeanName, Advice.class); } return this.advice; } }
那我们来看看AbstractBeanFactoryPointcutAdvisor和BeanFactoryTransactionAttributeSourceAdvisor的关系吧。从下图中,我们知道他们是继承关系。而从getAdvice方法中得知,advice是通过adviceBeanName从容器中获取的,而adviceBeanName又是在哪里设置的呢?我们回头再来看事务标签<tx:annotation-driven/>的解析,在adviceBeanName中,设置了adviceBeanName的值为interceptorName,而interceptorName对应的是容器中的TransactionInterceptor。经历过千辛万苦,终于得到的事务拦截器。下面我们将围绕着事务拦截器进行讲解。
ReflectiveMethodInvocation.java
public Object proceed() throws Throwable { if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { //直接调用目标方法 return invokeJoinpoint(); } Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice; if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) { return dm.interceptor.invoke(this); } else { //匹配失败,跳过拦截器执行 return proceed(); } } else { return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } }
从下图中可以得知TransactionInterceptor并没有实现InterceptorAndDynamicMethodMatcher的接口,因此直接调用TransactionInterceptor的invoke方法。
TransactionInterceptor.java
public Object invoke(final MethodInvocation invocation) throws Throwable { Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null); return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() { @Override public Object proceedWithInvocation() throws Throwable { //继续拦截器链调用 return invocation.proceed(); } }); }
事务增强器
TransactionInterceptor支撑着整个事务的功能架构,逻辑还是相对复杂的,那么现在我们切入正题来分析此拦截器是如何实现事务特性的,TransactionInterceptor类继承了MethodInterceptor,所以调用其invokeXXX方法开始,下面我们来看看这个方法。
TransactionAspectSupport.java
protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation) throws Throwable { //获取事务属性 final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass); //从beanFactory中获取事务管理器,在本博客中获取到的是DataSourceTransactionManager final PlatformTransactionManager tm = determineTransactionManager(txAttr); //获取类名+"."+方法名如:com.serviceImpl.updateById final String joinpointIdentification = methodIdentification(method, targetClass); //声明式事务处理 //从下图DataSourceTransactionManager的继承关系中得知DataSourceTransactionManager显然没有实现CallbackPreferringPlatformTransactionManager if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) { //获取事务信息 TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification); Object retVal = null; try { //继续调用拦截器链,如果没有其他拦截器的话,直接调用我们的目标方法 retVal = invocation.proceedWithInvocation(); } catch (Throwable ex) { //如果抛出异常,回滚数据 completeTransactionAfterThrowing(txInfo, ex); throw ex; } finally { //清理事务信息 cleanupTransactionInfo(txInfo); } //commit事务 commitTransactionAfterReturning(txInfo); return retVal; } else { //编程式事务处理 try { Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr, new TransactionCallback<Object>() { @Override public Object doInTransaction(TransactionStatus status) { TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status); try { return invocation.proceedWithInvocation(); } catch (Throwable ex) { if (txAttr.rollbackOn(ex)) { // A RuntimeException: will lead to a rollback. if (ex instanceof RuntimeException) { throw (RuntimeException) ex; } else { throw new ThrowableHolderException(ex); } } else { // A normal return value: will lead to a commit. return new ThrowableHolder(ex); } } finally { cleanupTransactionInfo(txInfo); } } }); // Check result: It might indicate a Throwable to rethrow. if (result instanceof ThrowableHolder) { throw ((ThrowableHolder) result).getThrowable(); } else { return result; } } catch (ThrowableHolderException ex) { throw ex.getCause(); } } }
从上面的函数中,我们尝试整理下事务的处理脉络,在Spring中支持两种事务的处理方式,分别是声明式事务处理和编程式事务处理,两者相对于开发人员来讲差别很大,但是对于Spring中的实现来讲,大同小异,在invoke中我们也看到了这两种方式的实现,考虑到对事务的应用比声明式事务的处理使用起来方便,也相对流行些,我们就以些方式进行解析,对于声明式事务的处理主要有以下的几个步骤。
- 获取事务的属性
对于事务处理来说,最基础或者说最重要的工作便是获取事务属性了,这是支撑整个事务的功能基石,如果没有事务属性,其他的功能也无从谈起,在分析事务准备阶段时我们己经分析了事务属性的提取的功能,大家应该有所了解。 - 加载配置中配置的TransactionManager。
- 不同的事务处理方式使用不同的逻辑。
对于声明式事务的处理与编程式事务的处理,第一点区别在于事务的属性上,因为编程式事务的处理是不需要有事务属性的,第二点,区别就是在于TransactionManager上,CallbackPreferringPlatformTransactionManager实现了PlatformTransactionManager接口,暴露出一个方法用于执行事务处理中的回调,所以,这两咱方式都可以用作事务处理方式的判断。 - 在目标方法执行前获取事务并收集事务信息
事务信息与事务属性并不相同,也就是TransactionInfo与TransactionAttribute并不相同,TransactionInfo中包含了TransactionAttribute信息,但是除了TransactionAttribute外还有其他的事务信息,例如:PlatformTransactionManager以及TransactionStatus相关信息。 - 执行目标方法。
- 一旦出现异常,尝试异常处理
并不是所有的异常都回滚,默认是对RuntimeException回滚。 - 提交事务前的事务信息擦除。
- 提交事务
上面的步骤分析旨在让大家对事务的功能与步骤有大致的了解,具体的功能还需要详细的分析。
TransactionAspectSupport.java
protected PlatformTransactionManager determineTransactionManager(TransactionAttribute txAttr) { //如果没有配置@Transactional注解或beanFactory为空,则从transactionManagerCache获取事务管理器 if (txAttr == null || this.beanFactory == null) { return getTransactionManager(); } //如果@Transactional中有qualifier属性,则获取方法自定义事务管理器 String qualifier = txAttr.getQualifier(); if (StringUtils.hasText(qualifier)) { return determineQualifiedTransactionManager(qualifier); } //当然,如果我们自定义了 //<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" /> //则使用我们自定义的事务管理器 else if (StringUtils.hasText(this.transactionManagerBeanName)) { return determineQualifiedTransactionManager(this.transactionManagerBeanName); } else { PlatformTransactionManager defaultTransactionManager = getTransactionManager(); if (defaultTransactionManager == null) { //如果以上情况都不符合,则从容器中获取一个实现了PlatformTransactionManager的bean作为事务管理器 defaultTransactionManager = this.beanFactory.getBean(PlatformTransactionManager.class); this.transactionManagerCache.putIfAbsent( DEFAULT_TRANSACTION_MANAGER_KEY, defaultTransactionManager); } return defaultTransactionManager; } } private PlatformTransactionManager determineQualifiedTransactionManager(String qualifier) { PlatformTransactionManager txManager = this.transactionManagerCache.get(qualifier); if (txManager == null) { //根据类型和名称从bean工厂中获取事务管理器 txManager = BeanFactoryAnnotationUtils.qualifiedBeanOfType( this.beanFactory, PlatformTransactionManager.class, qualifier); this.transactionManagerCache.putIfAbsent(qualifier, txManager); } return txManager; } }
创建事务
我们先来分析事务的创建过程。
TransactionAspectSupport.java
protected TransactionInfo createTransactionIfNecessary( PlatformTransactionManager tm, TransactionAttribute txAttr, final String joinpointIdentification) { if (txAttr != null && txAttr.getName() == null) { //如果没有名称指定则使用方法唯一标识,并使用DelegatingTransactionAttribute封装txAttr //如果txAttr的name为空,则以类名+"."+方法名作为txAttr的name txAttr = new DelegatingTransactionAttribute(txAttr) { @Override public String getName() { return joinpointIdentification; } }; } TransactionStatus status = null; if (txAttr != null) { if (tm != null) { //获取TransactionStatus status = tm.getTransaction(txAttr); } else { if (logger.isDebugEnabled()) { logger.debug("Skipping transactional joinpoint [" + joinpointIdentification + "] because no transaction manager has been configured"); } } } //根据指定的属性与status准备一个TransactionInfo return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status); }
对于createTransactionIfNecessary函数主要做了这样的几件事情。
- 使用DelegatingTransactionAttribute封装传入的TransactionAttribute实例
对于传入的TransactionAttribute类型的参数txAttr,当前的实际类型是RuleBaseTransactionAttribute,是由获取事务属性时生成,主要用于数据承载,而这里之所以使用DelegatingTransactionAttribute进行封装,当然是提供了更多的功能。 - 获取事务
事务处理当然以事务为核心,那么获取事务就是最重要的事情 。 - 构建事务信息
根据之前的几个步骤获取信息构建TransactionInfo并返回。
我们分别对以上的步骤进行详细的解析。
获取事务
AbstractPlatformTransactionManager.java
public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException { //获取事务对象 Object transaction = doGetTransaction(); boolean debugEnabled = logger.isDebugEnabled(); if (definition == null) { definition = new DefaultTransactionDefinition(); } //如果当前线程中事务存在,判断的依据为当前线程记录的连接不为空且连接中的(connectionHolder)中的 //transactionActive属性不为空 //(txObject.getConnectionHolder() != null && txObject.getConnectionHolder().isTransactionActive()); if (isExistingTransaction(transaction)) { //当前线程中己经存在事务 return handleExistingTransaction(definition, transaction, debugEnabled); } //如果事务超时,抛出异常 if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) { throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout()); } //如果事务的传播行为是PROPAGATION_MANDATORY,并且当前线程中己经存在事务,抛出异常 if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) { throw new IllegalTransactionStateException( "No existing transaction found for transaction marked with propagation 'mandatory'"); } //如果当前线程中不存在事务,并且事务的传播行为是PROPAGATION_REQUIRED,PROPAGATION_REQUIRES_NEW,PROPAGATION_NESTED //创建新事务 else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED || definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW || definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) { //空挂起 SuspendedResourcesHolder suspendedResources = suspend(null); if (debugEnabled) { logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition); } try { boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); DefaultTransactionStatus status = newTransactionStatus( definition, transaction, true, newSynchronization, debugEnabled, suspendedResources); //开启新事务,构造transaction,包括设置ConnectionHolder,隔离级别,timeout 如果是新连接,绑定到当前线程 doBegin(transaction, definition); //新同步事务的设置,针对于当前线程的设置 prepareSynchronization(status, definition); return status; } catch (RuntimeException ex) { resume(null, suspendedResources); throw ex; } catch (Error err) { resume(null, suspendedResources); throw err; } } else { if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) { logger.warn("Custom isolation level specified but no actual transaction initiated; " + "isolation level will effectively be ignored: " + definition); } boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS); return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null); } }
当然,在Spring中每个复杂的功能实现,并不是一次完成的,而是通过入口函数进行一个框架的搭建,初步构建完成的逻辑,而将实现的细节分摊给不同的函数,那么,让我们看看事务准备工作都包括了哪些。
- 获取事务
创建对应的事务实例,这里使用的是DataSourceTransactionManager中的doGetTransaction方法,创建基于JDBC的事务实例,如果当前线程中存在关于dataSource的连接,那么直接使用,这里有一个保存点的设置,是否开启允许保存点取决于是否设置了允许嵌入式事务。
DataSourceTransactionManager.java
protected Object doGetTransaction() { DataSourceTransactionObject txObject = new DataSourceTransactionObject(); //设置是否允许设置保存点 txObject.setSavepointAllowed(isNestedTransactionAllowed()); //如果当前线程己经记录了数据库软链接则使用原有链接 ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(this.dataSource); //false表示非新创建的连接 txObject.setConnectionHolder(conHolder, false); return txObject; }
- 如果当前线程中存在事务,则转向嵌套事务的处理
- 事务超时设置验证
- 事务propagationBehavior属性设置验证
- 构建DefaultTransactionStatus
- 完善transaction,包括设置ConnectionHolder,隔离级别,timeout,如果是新连接,则绑定到当前线程中。
处理己经存在的事务
之前讲述了普通 事务建立的过程,但是在Spring中支持多种事务的传播行为,比如PROPAGATION_REQUIRES_NEW,PROPAGATION_REQUIRED,PROPAGATION_SUPPORTS等,这些都是己经存在的事务的基础上进行进一步处理,那么对于己经存在的事务,准备操作是如何进行的呢?
AbstractPlatformTransactionManager.java
private TransactionStatus handleExistingTransaction( TransactionDefinition definition, Object transaction, boolean debugEnabled) throws TransactionException { //如果当前事务的传播行为是PROPAGATION_NEVER,抛出异常 if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) { throw new IllegalTransactionStateException( "Existing transaction found for transaction marked with propagation 'never'"); } //如果当前事务传播行为是不支持事务的,则挂起当前事务 if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) { if (debugEnabled) { logger.debug("Suspending current transaction"); } //挂起当前事务 Object suspendedResources = suspend(transaction); boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS); return prepareTransactionStatus( definition, null, false, newSynchronization, debugEnabled, suspendedResources); } //如果事务隔离级别是PROPAGATION_REQUIRES_NEW if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) { if (debugEnabled) { logger.debug("Suspending current transaction, creating new transaction with name [" + definition.getName() + "]"); } //挂起当前事务 SuspendedResourcesHolder suspendedResources = suspend(transaction); try { boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); //创建新的事务状态 DefaultTransactionStatus status = newTransactionStatus( definition, transaction, true, newSynchronization, debugEnabled, suspendedResources); //开启事务 doBegin(transaction, definition); //准备同步事务 prepareSynchronization(status, definition); return status; } catch (RuntimeException beginEx) { resumeAfterBeginException(transaction, suspendedResources, beginEx); throw beginEx; } catch (Error beginErr) { resumeAfterBeginException(transaction, suspendedResources, beginErr); throw beginErr; } } //说明: 如果当前存在事务,则使用 SavePoint 技术把当前事务状态进行保存, //然后底层共用一个连接,当NESTED内部出错的时候,自行回滚到 SavePoint这个状态,只要外部捕获到了异常, //就可以继续进行外部的事务提交,而不会受到内嵌业务的干扰,但是,如果外部事务抛出了异常,整个大事务都会回滚。 //注意: spring配置事务管理器要主动指定 nestedTransactionAllowed=true,如下所示: //<bean id="dataTransactionManager" //class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> // <property name="dataSource" ref="dataDataSource" /> // <property name="nestedTransactionAllowed" value="true" /> //</bean> if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) { if (!isNestedTransactionAllowed()) { throw new NestedTransactionNotSupportedException( "Transaction manager does not allow nested transactions by default - " + "specify 'nestedTransactionAllowed' property with value 'true'"); } if (debugEnabled) { logger.debug("Creating nested transaction with name [" + definition.getName() + "]"); } if (useSavepointForNestedTransaction()) { //如果没有可以使用的保存点的方式控制事务回滚,那么嵌入式事务的建立初始建立保存点。 DefaultTransactionStatus status = prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null); //创建并持有保存点 status.createAndHoldSavepoint(); return status; } else { //通过嵌套的begin和commit / rollback调用进行嵌套的事务。 // 有些情况是不能使用保存点的,比如JTA,那么建立新事务 boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); //这就是跟PROPAGATION_REQUIRES_NEW不一样的地方了,NESTED方式下的内嵌业务会受到外部事务的异常而回滚。 DefaultTransactionStatus status = newTransactionStatus( definition, transaction, true, newSynchronization, debugEnabled, null); doBegin(transaction, definition); prepareSynchronization(status, definition); return status; } } if (debugEnabled) { logger.debug("Participating in existing transaction"); } //如果事务的传播行为是PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED. if (isValidateExistingTransaction()) { //如果当前存在事务,但隔离级别不相等 if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) { Integer currentIsolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel(); //如果当前事务的级别为空或当前事务的隔离级别与新事务不相等,抛出异常 if (currentIsolationLevel == null || currentIsolationLevel != definition.getIsolationLevel()) { Constants isoConstants = DefaultTransactionDefinition.constants; throw new IllegalTransactionStateException("Participating transaction with definition [" + definition + "] specifies isolation level which is incompatible with existing transaction: " + (currentIsolationLevel != null ? isoConstants.toCode(currentIsolationLevel, DefaultTransactionDefinition.PREFIX_ISOLATION) : "(unknown)")); } } //如果事务属性定义的readOnly为为false,但是当前事务的readOnly为true ,抛出异常 if (!definition.isReadOnly()) { if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) { throw new IllegalTransactionStateException("Participating transaction with definition [" + definition + "] is not marked as read-only but existing transaction is"); } } } boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); //准备事务状态 return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null); }
对于己经存在的事务的处理过程,我们看到了很多的熟悉的操作,但是有些地方还是不同的,函数中对己经存在的事务处理考虑分为两种情况。
- PROPAGATION_REQUIRES_NEW:表示当前方法必需在它自己的事务里运行,一个新的事务将被启动,而如果一个事务正在运行的话,则在这个方法运行期间被挂起,而Spring中对于此种传播方式的处理与新事务建立最大的不同点在于使用了suspend方法将原来的事务挂起,将信息挂起的目的就是为了当前事务执行完毕后在将原事务还原。
- PROPAGATION_NESTED:表示如果当前正有一个事务在运行中,则该方法应该运行在一个嵌套的事务中,被嵌套的事务可以独立于封装事务进行提交或者回滚,如果封装事务不存在,行为就像PROPAGATION_REQUIRES_NEW,对于嵌入式事务的处理,Spring中主要考虑了两种方式处理。
- Spring中允许嵌入式事务的时候,则首选设置保存点的方式作为异常处理回滚。
- 对于其他的方式,比如JTA无法使用保存点的方式,那么处理方式与PROPAGATION_REQUIRES_NEW相同,而一旦出现异常,则由Spring事务异常处理机制去完成后续操作。
由于挂起操作的主要目的是记录原有事务的状态,以便后续操作对事务的恢复。
AbstractPlatformTransactionManager.java
protected final SuspendedResourcesHolder suspend(Object transaction) throws TransactionException { //同步事务是否激活 if (TransactionSynchronizationManager.isSynchronizationActive()) { List<TransactionSynchronization> suspendedSynchronizations = doSuspendSynchronization(); try { Object suspendedResources = null; if (transaction != null) { //真正的挂起数据库资源 suspendedResources = doSuspend(transaction); } //获取当前事务名称 String name = TransactionSynchronizationManager.getCurrentTransactionName(); TransactionSynchronizationManager.setCurrentTransactionName(null); //获取当前事务只读状态 boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly(); TransactionSynchronizationManager.setCurrentTransactionReadOnly(false); //获取事务隔离级别 Integer isolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel(); TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(null); //当前事务是否激活 boolean wasActive = TransactionSynchronizationManager.isActualTransactionActive(); TransactionSynchronizationManager.setActualTransactionActive(false); //将这些信息都封装到挂起资源持有者对象中 return new SuspendedResourcesHolder( suspendedResources, suspendedSynchronizations, name, readOnly, isolationLevel, wasActive); } catch (RuntimeException ex) { //如果抛出异常,恢复同步事务资源 doResumeSynchronization(suspendedSynchronizations); throw ex; } catch (Error err) { //如果抛出Error,恢复同步事务资源 doResumeSynchronization(suspendedSynchronizations); throw err; } } else if (transaction != null) { //有事务,但是没有同步激活 Object suspendedResources = doSuspend(transaction); //将事务资源保存并返回 return new SuspendedResourcesHolder(suspendedResources); } else { //从来没有事务或者事务同步事务都没有被激活 return null; } }
AbstractPlatformTransactionManager.java
private List<TransactionSynchronization> doSuspendSynchronization() { //获取当前的所有同步事务并将其挂起 List<TransactionSynchronization> suspendedSynchronizations = TransactionSynchronizationManager.getSynchronizations(); for (TransactionSynchronization synchronization : suspendedSynchronizations) { synchronization.suspend(); } //清除同步事务 TransactionSynchronizationManager.clearSynchronization(); //返回被清除的同步事务 return suspendedSynchronizations; }
TransactionSynchronizationManager.java
private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations = new NamedThreadLocal<Set<TransactionSynchronization>>("Transaction synchronizations"); public static void clearSynchronization() throws IllegalStateException { if (!isSynchronizationActive()) { throw new IllegalStateException("Cannot deactivate transaction synchronization - not active"); } logger.trace("Clearing transaction synchronization"); synchronizations.remove(); }
DataSourceTransactionManager.java
protected Object doSuspend(Object transaction) { DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction; //释放链接 txObject.setConnectionHolder(null); //解绑数据库资源 ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.unbindResource(this.dataSource); return conHolder; }
public static Object unbindResource(Object key) throws IllegalStateException { Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key); Object value = doUnbindResource(actualKey); if (value == null) { throw new IllegalStateException( "No value for key [" + actualKey + "] bound to thread [" + Thread.currentThread().getName() + "]"); } return value; } private static Object doUnbindResource(Object actualKey) { Map<Object, Object> map = resources.get(); if (map == null) { return null; } Object value = map.remove(actualKey); if (map.isEmpty()) { resources.remove(); } if (value instanceof ResourceHolder && ((ResourceHolder) value).isVoid()) { value = null; } if (value != null && logger.isTraceEnabled()) { logger.trace("Removed value [" + value + "] for key [" + actualKey + "] from thread [" + Thread.currentThread().getName() + "]"); } return value; }
AbstractPlatformTransactionManager.java
private void doResumeSynchronization(List<TransactionSynchronization> suspendedSynchronizations) { //初始化当前线程的同步事务 TransactionSynchronizationManager.initSynchronization(); //恢复同步事务 for (TransactionSynchronization synchronization : suspendedSynchronizations) { //恢复同步事务 synchronization.resume(); //将同步事务注册到当前线程 TransactionSynchronizationManager.registerSynchronization(synchronization); } }
TransactionSynchronizationManager.java
public static void registerSynchronization(TransactionSynchronization synchronization) throws IllegalStateException { Assert.notNull(synchronization, "TransactionSynchronization must not be null"); if (!isSynchronizationActive()) { throw new IllegalStateException("Transaction synchronization is not active"); } synchronizations.get().add(synchronization); }
protected final DefaultTransactionStatus prepareTransactionStatus( TransactionDefinition definition, Object transaction, boolean newTransaction, boolean newSynchronization, boolean debug, Object suspendedResources) { DefaultTransactionStatus status = newTransactionStatus( definition, transaction, newTransaction, newSynchronization, debug, suspendedResources); prepareSynchronization(status, definition); return status; } protected DefaultTransactionStatus newTransactionStatus( TransactionDefinition definition, Object transaction, boolean newTransaction, boolean newSynchronization, boolean debug, Object suspendedResources) { boolean actualNewSynchronization = newSynchronization && !TransactionSynchronizationManager.isSynchronizationActive(); return new DefaultTransactionStatus( transaction, newTransaction, actualNewSynchronization, definition.isReadOnly(), debug, suspendedResources); }
将事务信息记录在当前线程中。
protected void prepareSynchronization(DefaultTransactionStatus status, TransactionDefinition definition) { if (status.isNewSynchronization()) { TransactionSynchronizationManager.setActualTransactionActive(status.hasTransaction()); //设置当前线程事务的隔离级别 TransactionSynchronizationManager.setCurrentTransactionIsolationLevel( definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT ? definition.getIsolationLevel() : null); //设置当前线程事务的可读性 TransactionSynchronizationManager.setCurrentTransactionReadOnly(definition.isReadOnly()); //设置当前线程事务的名称 TransactionSynchronizationManager.setCurrentTransactionName(definition.getName()); //初始化当前线程同步事务 TransactionSynchronizationManager.initSynchronization(); } }
对于一些隔离级别,timeout等功能的设置并不是由Spring来完成的,而是委托给数据库连接去做的,对于数据库连接的设置就是在doBegin函数中处理。
DataSourceTransactionManager.java
//构造transaction,包括设置ConnectionHolder,隔离级别,timeout,如果是新连接,绑定到当前线程 protected void doBegin(Object transaction, TransactionDefinition definition) { DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction; Connection con = null; try { if (txObject.getConnectionHolder() == null || txObject.getConnectionHolder().isSynchronizedWithTransaction()) { Connection newCon = this.dataSource.getConnection(); if (logger.isDebugEnabled()) { logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction"); } txObject.setConnectionHolder(new ConnectionHolder(newCon), true); } txObject.getConnectionHolder().setSynchronizedWithTransaction(true); con = txObject.getConnectionHolder().getConnection(); //设置事务的隔离级别 Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition); txObject.setPreviousIsolationLevel(previousIsolationLevel); //将事务提交置,由Spring控制提交 if (con.getAutoCommit()) { txObject.setMustRestoreAutoCommit(true); if (logger.isDebugEnabled()) { logger.debug("Switching JDBC Connection [" + con + "] to manual commit"); } con.setAutoCommit(false); } //设置当前线程是否存在事务的依据 txObject.getConnectionHolder().setTransactionActive(true); int timeout = determineTimeout(definition); //设置事务超时时间 if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) { txObject.getConnectionHolder().setTimeoutInSeconds(timeout); } if (txObject.isNewConnectionHolder()) { //将当前获取到的连接绑定到当前线程 TransactionSynchronizationManager.bindResource(getDataSource(), txObject.getConnectionHolder()); } } catch (Throwable ex) { //事务开启失败,释放资源 if (txObject.isNewConnectionHolder()) { DataSourceUtils.releaseConnection(con, this.dataSource); txObject.setConnectionHolder(null, false); } throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex); } }
可以说事务是从这个函数开始的,因为在这个函数中己经开始尝试了,数据库连接的获取,当然在获取数据库连接的同时,一些必要的设置也是需要同步设置的。
- 尝试获取连接
当然并不是每次都会获取新的连接,如果当前线程中connectionHolder己经存在,则没有必要再次获取,或者对于事务同步表示设置为true的需要重要获取连接。 - 设置隔离级别及只读标识
你是否有过这样的错觉?事务的只读配置是Spring中做了一些处理呢?Spring确实是针对只读操作做了一些处理,但是核心的实现是设置connection上的readOnly属性,同样,对于隔离级别上的控制也交由connection去控制的。 - 更改默认的提交设置
如果事务属性是自动提交的,那么需要改变这种设置,而是将提交操作委托给Spring来处理。 - 设置标志位,标识当前连接己经被事务激活。
- 设置过期时间
- 将connectionHolder绑定到当前线程
设置隔离级别的prepareConnectionForTransaction函数用于负责对底层数据库连接的设置,当然,只是包含只读标识和隔离级别的设置,由于强大的日志及异常处理,显得函数代码量比较大,但是单从业务的角度上去看,关键代码其实是不多的。
public static Integer prepareConnectionForTransaction(Connection con, TransactionDefinition definition) throws SQLException { Assert.notNull(con, "No Connection specified"); //设置数据库连接的只读标识 if (definition != null && definition.isReadOnly()) { try { if (logger.isDebugEnabled()) { logger.debug("Setting JDBC Connection [" + con + "] read-only"); } con.setReadOnly(true); } catch (SQLException ex) { Throwable exToCheck = ex; while (exToCheck != null) { if (exToCheck.getClass().getSimpleName().contains("Timeout")) { // Assume it's a connection timeout that would otherwise get lost: e.g. from JDBC 4.0 throw ex; } exToCheck = exToCheck.getCause(); } // "read-only not supported" SQLException -> ignore, it's just a hint anyway logger.debug("Could not set JDBC Connection read-only", ex); } catch (RuntimeException ex) { Throwable exToCheck = ex; while (exToCheck != null) { if (exToCheck.getClass().getSimpleName().contains("Timeout")) { // Assume it's a connection timeout that would otherwise get lost: e.g. from Hibernate throw ex; } exToCheck = exToCheck.getCause(); } // "read-only not supported" UnsupportedOperationException -> ignore, it's just a hint anyway logger.debug("Could not set JDBC Connection read-only", ex); } } //设置数据库连接的隔离级别 Integer previousIsolationLevel = null; if (definition != null && definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) { if (logger.isDebugEnabled()) { logger.debug("Changing isolation level of JDBC Connection [" + con + "] to " + definition.getIsolationLevel()); } int currentIsolation = con.getTransactionIsolation(); if (currentIsolation != definition.getIsolationLevel()) { previousIsolationLevel = currentIsolation; con.setTransactionIsolation(definition.getIsolationLevel()); } } return previousIsolationLevel; }
准备事务信息
当前己经建立事务并完成了事务信息提取后,我们需要将所有的事务信息统一记录在TransactionInfo类型的实例中,这个实例包含了目标方法开始前的所有状态信息。一旦事务执行失败,Spring会通过TransactionInfo类型的实例中的信息来进行回滚等后续工作。
TransactionAspectSupport.java
private static final ThreadLocal<TransactionInfo> transactionInfoHolder = new NamedThreadLocal<TransactionInfo>("Current aspect-driven transaction"); protected TransactionInfo prepareTransactionInfo(PlatformTransactionManager tm, TransactionAttribute txAttr, String joinpointIdentification, TransactionStatus status) { TransactionInfo txInfo = new TransactionInfo(tm, txAttr, joinpointIdentification); //如果事务属性不为空 if (txAttr != null) { if (logger.isTraceEnabled()) { logger.trace("Getting transaction for [" + txInfo.getJoinpointIdentification() + "]"); } //创建新的事务状态 txInfo.newTransactionStatus(status); } else { if (logger.isTraceEnabled()) logger.trace("Don't need to create transaction for [" + joinpointIdentification + "]: This method isn't transactional."); } //事务信息绑定到当前线程 txInfo.bindToThread(); return txInfo; }
TransactionInfo.java
private void bindToThread() { this.oldTransactionInfo = transactionInfoHolder.get(); transactionInfoHolder.set(this); }
回滚处理
之前己经完成了目标方法进行前的事务准备工作,而这些准备工作最大的目的无非是对于程序没有我们期待的那样进行,也就是出现特定的错误,那么,当出现错误的时候,Spring会怎样恢复数据呢?
TransactionAspectSupport.java
protected void completeTransactionAfterThrowing(TransactionInfo txInfo, Throwable ex) { //当程序抛出异常时首先判断当前是否存在事务,这是基础依据 if (txInfo != null && txInfo.hasTransaction()) { if (logger.isTraceEnabled()) { logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "] after exception: " + ex); } //这里判断是否回滚默认的依据是抛出的异常是否是 RuntimeException 或 Error if (txInfo.transactionAttribute.rollbackOn(ex)) { try { //根据TransactionStatus回滚事务 txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus()); } catch (TransactionSystemException ex2) { logger.error("Application exception overridden by rollback exception", ex); ex2.initApplicationException(ex); throw ex2; } catch (RuntimeException ex2) { logger.error("Application exception overridden by rollback exception", ex); throw ex2; } catch (Error err) { logger.error("Application exception overridden by rollback error", ex); throw err; } } else { //如果不符合事务回滚条件,则提交事务 try { txInfo.getTransactionManager().commit(txInfo.getTransactionStatus()); } catch (TransactionSystemException ex2) { logger.error("Application exception overridden by commit exception", ex); ex2.initApplicationException(ex); throw ex2; } catch (RuntimeException ex2) { logger.error("Application exception overridden by commit exception", ex); throw ex2; } catch (Error err) { logger.error("Application exception overridden by commit error", ex); throw err; } } } }
在对目标方法执行的过程中,一旦出现Throwable就会被引导至此方法处理,但是并不代表所有的Throwable都会被回滚处理,比如我们常用的Exception,默认是不会被处理的,默认情况下,即使出现异常,数据也会被正常提交,而这个关键的地方就是txInfo.transactionAttribute.rollbackOn(ex)这个函数。
1.回滚条件
public boolean rollbackOn(Throwable ex) { return (ex instanceof RuntimeException || ex instanceof Error); }
看到了吗?默认情况下Spring中的事务异常处理机制只对RutimeException和Error两种情况感兴趣,当然你可以通过扩展来改变,不过我们最常用的还是使用事务提供的属性设置,利用注解的方式使用,例如:
@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
回滚处理
当然,一旦符合回滚条件,那么Spring就会将程序引导至回滚处理函数中。
AbstractPlatformTransactionManager.java
public final void rollback(TransactionStatus status) throws TransactionException { //如果事务己经完成,再次回滚会抛出异常 if (status.isCompleted()) { throw new IllegalTransactionStateException( "Transaction is already completed - do not call commit or rollback more than once per transaction"); } DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status; //处理事务回滚 processRollback(defStatus); }
AbstractPlatformTransactionManager.java
private void processRollback(DefaultTransactionStatus status) { try { try { //激活所有的TransactionSyschronization中对应的方法 triggerBeforeCompletion(status); //如果事务状态中有保存点,回滚到保存点 if (status.hasSavepoint()) { if (status.isDebug()) { logger.debug("Rolling back transaction to savepoint"); } //如果有保存点,也就是当前事务为单独的线程则会退到保存点 status.rollbackToHeldSavepoint(); } //如果是新事务,则直接回退 else if (status.isNewTransaction()) { if (status.isDebug()) { logger.debug("Initiating transaction rollback"); } //回滚事务 doRollback(status); } //如果是嵌套事务,则设置总事务为 else if (status.hasTransaction()) { if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) { if (status.isDebug()) { logger.debug("Participating transaction failed - marking existing transaction as rollback-only"); } //如果当前事务不是独立的事务,那么只能标记状态,等到事务链执行完毕后统一回滚 doSetRollbackOnly(status); } else { if (status.isDebug()) { logger.debug("Participating transaction failed - letting transaction originator decide on rollback"); } } } else { logger.debug("Should roll back transaction but cannot - no transaction available"); } } catch (RuntimeException ex) { //激活所有的TransactionSynchronization中对应的方法 triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN); throw ex; } catch (Error err) { //激活所有的TransactionSynchronization中对应的方法 triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN); throw err; } //激活所有的TransactionSynchronization中对应的方法 triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK); } finally { //回滚后释放资源 cleanupAfterCompletion(status); } }
关于rollback方法有很多的实现类,这里以DataSourceTransactionManager这个为例讲解。
同样,对于在Spring中复杂的逻辑处理过程,在入口函数一般都会给出整个的处理脉络,而把实现的细节委托给其他函数去执行,我们尝试总结一下Spring中对于回滚处理的大致脉络如下。
- 首先是自定义触发器的调用,包括在回滚前,完成回滚后的调用,当然 完成回滚包括正常回滚与回滚过程中出现异常,自定义的触发器会根据这些信息作为进一步的处理,而对于触发器的注册常见的是回调过程中通过TransactionSynchronizationManager类中静态方法直接注册:
public static void registerSynchronization(TransactionSynchronization synchronization){…} - 除了触发监听函数外,就是真正的回滚逻辑的处理了。
- 当之前己经保存的事务信息中有保存点信息时候,使用保存点信息进行回滚,常用于嵌入式事务,对于嵌入式事务的处理,内嵌的事务异常并不会引起外部事务的回滚。
根据保存点回滚的实现方式其实是根据底层的数据库连接进行的。
AbstractTransactionStatus.java
public void rollbackToHeldSavepoint() throws TransactionException { if (!hasSavepoint()) { throw new TransactionUsageException( "Cannot roll back to savepoint - no savepoint associated with current transaction"); } getSavepointManager().rollbackToSavepoint(getSavepoint()); getSavepointManager().releaseSavepoint(getSavepoint()); setSavepoint(null); }
这里使用的是JDBC的方式进行数据库连接,那么getSavepointManager函数返回的是JdbcTransactionObjectSupport,也就是说上面的函数会调用JdbcTransactionObjectSupport中的rollbackToSavepoint方法。
JdbcTransactionObjectSupport.java
public void rollbackToSavepoint(Object savepoint) throws TransactionException { ConnectionHolder conHolder = getConnectionHolderForSavepoint(); try { conHolder.getConnection().rollback((Savepoint) savepoint); } catch (Throwable ex) { throw new TransactionSystemException("Could not roll back to JDBC savepoint", ex); } }
- 当前己经保存的事务信息中的事务为新事务,那么直接回滚,常用于单独事务的处理,对于没有保存点的回滚,Spring同样是使用底层数据库连接提供的Api来操作的,由于我们使用的是DataSourceTransactionManager,那么doRollback函数会使用此类中的实现。
DataSourceTransactionManager.java
protected void doRollback(DefaultTransactionStatus status) { DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction(); Connection con = txObject.getConnectionHolder().getConnection(); if (status.isDebug()) { logger.debug("Rolling back JDBC transaction on Connection [" + con + "]"); } try { //事务回滚 con.rollback(); } catch (SQLException ex) { throw new TransactionSystemException("Could not roll back JDBC transaction", ex); } }
- 当前事务信息中表明是存在事务的,又不属于以上的两种情况,多数用于JTA,只做回滚标识,等到提交的时候统一不提交。
protected void doSetRollbackOnly(DefaultTransactionStatus status) { DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction(); if (status.isDebug()) { logger.debug("Setting JDBC transaction [" + txObject.getConnectionHolder().getConnection() + "] rollback-only"); } txObject.setRollbackOnly(); }
回滚后的信息清除
对于回滚逻辑执行结束后,无论回滚是否成功,都必需要做的事情就是事务结束后的收尾工作。
private void cleanupAfterCompletion(DefaultTransactionStatus status) { //设置事务状态为己经完成 status.setCompleted(); if (status.isNewSynchronization()) { //如果当前事务状态是新的同步事务 TransactionSynchronizationManager.clear(); } if (status.isNewTransaction()) { doCleanupAfterCompletion(status.getTransaction()); } if (status.getSuspendedResources() != null) { if (status.isDebug()) { logger.debug("Resuming suspended transaction after completion of inner transaction"); } //结束之前事务的挂起状态 resume(status.getTransaction(), (SuspendedResourcesHolder) status.getSuspendedResources()); } }
TransactionSynchronizationManager.java
public static void clear() { //清理掉其他的同步事务信息 clearSynchronization(); //清理掉当前事务信息 setCurrentTransactionName(null); setCurrentTransactionReadOnly(false); setCurrentTransactionIsolationLevel(null); setActualTransactionActive(false); }
public static void clearSynchronization() throws IllegalStateException { if (!isSynchronizationActive()) { throw new IllegalStateException("Cannot deactivate transaction synchronization - not active"); } logger.trace("Clearing transaction synchronization"); synchronizations.remove(); }
从函数中得知,事务处理的收尾工作包括如下内容:
- 设置状态是对事务信息作完成标识以避免重复调用。
- 如果当前事务是新的同步状态,需要将绑定到当前线程的事务信息清除
- 如果是新事务需要做些清除资源的工作
protected void doCleanupAfterCompletion(Object transaction) { DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction; if (txObject.isNewConnectionHolder()) { //将数据库连接从当前线程中解析绑定 TransactionSynchronizationManager.unbindResource(this.dataSource); } //释放链接 Connection con = txObject.getConnectionHolder().getConnection(); try { if (txObject.isMustRestoreAutoCommit()) { //恢复数据库连接的自动提交属性 con.setAutoCommit(true); } //重置数据库连接 DataSourceUtils.resetConnectionAfterTransaction(con, txObject.getPreviousIsolationLevel()); } catch (Throwable ex) { logger.debug("Could not reset JDBC Connection after transaction", ex); } if (txObject.isNewConnectionHolder()) { if (logger.isDebugEnabled()) { logger.debug("Releasing JDBC Connection [" + con + "] after transaction"); } //如果当前事务时独立的新创建的事务则在事务完成时释放数据库连接 DataSourceUtils.releaseConnection(con, this.dataSource); } txObject.getConnectionHolder().clear(); }
- 如果在事务执行前有事务挂起,那么当前事务执行结束后需要将挂起事务恢复
AbstractPlatformTransactionManager.java
protected final void resume(Object transaction, SuspendedResourcesHolder resourcesHolder) throws TransactionException { if (resourcesHolder != null) { Object suspendedResources = resourcesHolder.suspendedResources; if (suspendedResources != null) { doResume(transaction, suspendedResources); } List<TransactionSynchronization> suspendedSynchronizations = resourcesHolder.suspendedSynchronizations; if (suspendedSynchronizations != null) { //将挂起的事务信息恢复到当前事务 TransactionSynchronizationManager.setActualTransactionActive(resourcesHolder.wasActive); TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(resourcesHolder.isolationLevel); TransactionSynchronizationManager.setCurrentTransactionReadOnly(resourcesHolder.readOnly); TransactionSynchronizationManager.setCurrentTransactionName(resourcesHolder.name); //恢复所有的同步事务 doResumeSynchronization(suspendedSynchronizations); } } }
DataSourceTransactionManager.java
protected void doResume(Object transaction, Object suspendedResources) { ConnectionHolder conHolder = (ConnectionHolder) suspendedResources; TransactionSynchronizationManager.bindResource(this.dataSource, conHolder); }
TransactionSynchronizationManager.java
public static void bindResource(Object key, Object value) throws IllegalStateException { Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key); Assert.notNull(value, "Value must not be null"); Map<Object, Object> map = resources.get(); //当前线程中没有map if (map == null) { map = new HashMap<Object, Object>(); resources.set(map); } Object oldValue = map.put(actualKey, value); if (oldValue instanceof ResourceHolder && ((ResourceHolder) oldValue).isVoid()) { oldValue = null; } //如果DataSource己经被绑定,抛出异常 if (oldValue != null) { throw new IllegalStateException("Already value [" + oldValue + "] for key [" + actualKey + "] bound to thread [" + Thread.currentThread().getName() + "]"); } if (logger.isTraceEnabled()) { logger.trace("Bound value [" + value + "] for key [" + actualKey + "] to thread [" + Thread.currentThread().getName() + "]"); } }
TransactionAspectSupport.java
protected void cleanupTransactionInfo(TransactionInfo txInfo) { if (txInfo != null) { txInfo.restoreThreadLocalStatus(); } }
TransactionInfo.java
private void restoreThreadLocalStatus() { //恢复当前线程中的事务信息为旧的事务信息 transactionInfoHolder.set(this.oldTransactionInfo); }
事务提交
之前我们分析了Spring的事务异常处理机制,那么事务的执行并没有出现任何的异常,也就意味着可以走正常的事务提交流程了。
TransactionAspectSupport.java
protected void commitTransactionAfterReturning(TransactionInfo txInfo) { if (txInfo != null && txInfo.hasTransaction()) { if (logger.isTraceEnabled()) { logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "]"); } //提交当前事务 txInfo.getTransactionManager().commit(txInfo.getTransactionStatus()); } }
在真正的数据提交之前,还需要做一个判断,不知道大家还有没有印象,在我们分析事务异常处理规则的时候,当某个事务既没有保存点又不是新事务,Spring对它的处理方式只是设置了一个回滚标识,这个回滚标识在这里就会派上用场了,主要应用场景如下。
某个事务是另一个事务的嵌入事务,但是,这些事务又不在Spring的管理范围,或者无法设置保存点,那么Spring会通过设置回滚标识的方式来禁止提交,首先当某个嵌入事务发生回滚的时候会设置回滚标识,而等到外部事务提交时,一旦判断出当前事务流被设置了回滚标识,则由外部事务来统一进行整体的事务回滚。
所以,当事务没有被异常捕获的情况的时候也并不意味着一定会执行提交的过程。
AbstractPlatformTransactionManager.java
public final void commit(TransactionStatus status) throws TransactionException { if (status.isCompleted()) { throw new IllegalTransactionStateException( "Transaction is already completed - do not call commit or rollback more than once per transaction"); } DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status; //如果事务链中己经被标记回滚,那么不会尝试提交事务,直接回滚 if (defStatus.isLocalRollbackOnly()) { if (defStatus.isDebug()) { logger.debug("Transactional code has requested rollback"); } processRollback(defStatus); return; } if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) { if (defStatus.isDebug()) { logger.debug("Global transaction is marked as rollback-only but transactional code requested commit"); } processRollback(defStatus); // Throw UnexpectedRollbackException only at outermost transaction boundary // or if explicitly asked to. if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) { throw new UnexpectedRollbackException( "Transaction rolled back because it has been marked as rollback-only"); } return; } //处理事务提交 processCommit(defStatus); }
AbstractPlatformTransactionManager.java
private void processCommit(DefaultTransactionStatus status) throws TransactionException { try { boolean beforeCompletionInvoked = false; try { //预留,为第三方包提交前做准备,如Hibernate prepareForCommit(status); //添加TransactionSynchronization中对应的方法调用 triggerBeforeCommit(status); //添加TransactionSynchronization中对应的方法调用 triggerBeforeCompletion(status); beforeCompletionInvoked = true; boolean globalRollbackOnly = false; if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) { globalRollbackOnly = status.isGlobalRollbackOnly(); } //如果有保存点,则释放保存点 if (status.hasSavepoint()) { if (status.isDebug()) { logger.debug("Releasing transaction savepoint"); } status.releaseHeldSavepoint(); } else if (status.isNewTransaction()) { if (status.isDebug()) { logger.debug("Initiating transaction commit"); } //如果是独立的事务,直接提交 doCommit(status); } if (globalRollbackOnly) { throw new UnexpectedRollbackException( "Transaction silently rolled back because it has been marked as rollback-only"); } } catch (UnexpectedRollbackException ex) { //添加TransactionSynchronization中对应的方法调用 triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK); throw ex; } catch (TransactionException ex) { if (isRollbackOnCommitFailure()) { //提交过程中出现异常则回滚 doRollbackOnCommitException(status, ex); } else { //添加TransactionSynchronization中对应的方法调用 triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN); } throw ex; } catch (RuntimeException ex) { if (!beforeCompletionInvoked) { triggerBeforeCompletion(status); } doRollbackOnCommitException(status, ex); throw ex; } catch (Error err) { if (!beforeCompletionInvoked) { triggerBeforeCompletion(status); } doRollbackOnCommitException(status, err); throw err; } try { triggerAfterCommit(status); } finally { triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED); } } finally { cleanupAfterCompletion(status); } }
AbstractPlatformTransactionManager.java
protected void prepareForCommit(DefaultTransactionStatus status) { }
AbstractPlatformTransactionManager.java
protected final void triggerBeforeCompletion(DefaultTransactionStatus status) { if (status.isNewSynchronization()) { if (status.isDebug()) { logger.trace("Triggering beforeCompletion synchronization"); } TransactionSynchronizationUtils.triggerBeforeCompletion(); } }
public static void triggerBeforeCompletion() { for (TransactionSynchronization synchronization : TransactionSynchronizationManager.getSynchronizations()) { try { synchronization.beforeCompletion(); } catch (Throwable tsex) { logger.error("TransactionSynchronization.beforeCompletion threw exception", tsex); } } }
AbstractPlatformTransactionManager.java
protected final void triggerBeforeCommit(DefaultTransactionStatus status) { if (status.isNewSynchronization()) { if (status.isDebug()) { logger.trace("Triggering beforeCommit synchronization"); } TransactionSynchronizationUtils.triggerBeforeCommit(status.isReadOnly()); } }
TransactionSynchronizationUtils.java
public static void triggerBeforeCommit(boolean readOnly) { for (TransactionSynchronization synchronization : TransactionSynchronizationManager.getSynchronizations()) { synchronization.beforeCommit(readOnly); } }
在提交的过程中并不是直接提交的,而是考虑了诸多的方面,符合提交的条件如下。
- 当事务状态中有保存点信息的话便不会去提交事务。
- 当事务非新事务的时候也不会去执行提交事务操作。
此条件主要考虑内嵌事务的情况,对于内嵌事务,在Spring中正常的处理方式是将内嵌事务开始之前设置保存点,一旦内嵌事务出现异常便会根据保存点信息进行回滚,但是如果没有出现异常,内嵌事务并不会单独提交,而是根据事务流由最外层事务负责提交,所以如果当前存在保存点信息便不是最外层事务,不做保存操作,对于是否是新事务的判断也是基于此考虑的。
如果程序流通过了事务的层层把关,最后顺利的进入了提交流程,那么同样,Spring会将事务提交的操作引导至底层数据库连接的API,进行事务提交。
protected void doCommit(DefaultTransactionStatus status) { DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction(); Connection con = txObject.getConnectionHolder().getConnection(); if (status.isDebug()) { logger.debug("Committing JDBC transaction on Connection [" + con + "]"); } try { con.commit(); } catch (SQLException ex) { throw new TransactionSystemException("Could not commit JDBC transaction", ex); } }
AbstractPlatformTransactionManager.java
private void doRollbackOnCommitException(DefaultTransactionStatus status, Throwable ex) throws TransactionException { try { if (status.isNewTransaction()) { if (status.isDebug()) { logger.debug("Initiating transaction rollback after commit exception", ex); } doRollback(status); } else if (status.hasTransaction() && isGlobalRollbackOnParticipationFailure()) { if (status.isDebug()) { logger.debug("Marking existing transaction as rollback-only after commit exception", ex); } doSetRollbackOnly(status); } } catch (RuntimeException rbex) { logger.error("Commit exception overridden by rollback exception", ex); triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN); throw rbex; } catch (Error rberr) { logger.error("Commit exception overridden by rollback exception", ex); triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN); throw rberr; } triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK); }
AbstractPlatformTransactionManager.java
private void triggerAfterCommit(DefaultTransactionStatus status) { if (status.isNewSynchronization()) { if (status.isDebug()) { logger.trace("Triggering afterCommit synchronization"); } TransactionSynchronizationUtils.triggerAfterCommit(); } } ###### TransactionSynchronizationUtils.java public static void triggerAfterCommit() { invokeAfterCommit(TransactionSynchronizationManager.getSynchronizations()); } public static void invokeAfterCommit(List synchronizations) { if (synchronizations != null) { for (TransactionSynchronization synchronization : synchronizations) { synchronization.afterCommit(); } } }
在提交或者回滚操作的时候,都有TransactionSynchronization中对应的方法调用,那这个方法的调用有什么用呢?来看下面的例子。
例1.1
- 创建Event
public class MyTransactionEvent extends ApplicationEvent { private String name; public MyTransactionEvent(String name, Object source) { super(source); this.name = name; } public String getName() { return this.name; } }
- 创建事件监听器
@Component public class MyTransactionListener { @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) public void handlerTransactionCommit(MyTransactionEvent event) { if(event instanceof MyTransactionEvent){ System.out.println("==========事件提交了===============" + event.getName()); } } @TransactionalEventListener(phase = TransactionPhase.AFTER_ROLLBACK) public void handlerTransactionRollBack(MyTransactionEvent event) { if(event instanceof MyTransactionEvent){ System.out.println("==========事务回滚了===============" + event.getName()); } } }
- 创建ServiceImpl开始测试
@Transactional(propagation = Propagation.REQUIRES_NEW) public void updateUserRequiresNew1() { applicationEventPublisher.publishEvent(new MyTransactionEvent("我是和事务相关的事件,请事务提交后执行我~~~", 1)); System.out.println(">>>>>>>>>>>>>>>>开始更新>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); User user2 = selectById(457l); user2.setUsername("456"); updateById(user2); int i = 0 ; int j = 1; int k = j / i ; }
有兴趣的读者可以到gitHub上去下载代码,很多的细节上的配置,这里就不再赘述。
- 创建Spring配置文件
<?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:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven> <context:component-scan base-package="com.spring_101_200.test_181_190.test_181_commit_rollback_listener"></context:component-scan> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <bean id="userService" class="com.spring_101_200.test_181_190.test_181_commit_rollback_listener.UserServiceImpl"> <property name="jdbcTemplate" ref="dataSource"></property> </bean> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://172.16.157.238:3306/pple_test?characterEncoding=utf-8"></property> <property name="username" value="ldd_biz"></property> <property name="password" value="Hello1234"></property> <property name="initialSize" value="1"></property> <property name="maxIdle" value="2"></property> <property name="minIdle" value="1"></property> </bean> </beans>
- 测试
public class Test181 { public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext("spring_101_200/config_181_190/spring181.xml"); UserService userService = (UserService) ac.getBean("userService"); userService.updateUserRequiresNew1(); } }
- 测试结果
抛出了异常,事务回滚,并打印了事务回滚的日志。那么handlerTransactionRollBack方法是在哪里被调用的呢?看下图
AbstractPlatformTransactionManager.java
private void triggerAfterCompletion(DefaultTransactionStatus status, int completionStatus) { if (status.isNewSynchronization()) { List<TransactionSynchronization> synchronizations = TransactionSynchronizationManager.getSynchronizations(); if (!status.hasTransaction() || status.isNewTransaction()) { if (status.isDebug()) { logger.trace("Triggering afterCompletion synchronization"); } // No transaction or new transaction for the current scope -> // invoke the afterCompletion callbacks immediately invokeAfterCompletion(synchronizations, completionStatus); } else if (!synchronizations.isEmpty()) { // Existing transaction that we participate in, controlled outside // of the scope of this Spring transaction manager -> try to register // an afterCompletion callback with the existing (JTA) transaction. registerAfterCompletionWithExistingTransaction(status.getTransaction(), synchronizations); } } }
AbstractPlatformTransactionManager.java
protected void registerAfterCompletionWithExistingTransaction( Object transaction, List<TransactionSynchronization> synchronizations) throws TransactionException { logger.debug("Cannot register Spring after-completion synchronization with existing transaction - " + "processing Spring after-completion callbacks immediately, with outcome status 'unknown'"); //STATUS_UNKNOWN = 2 invokeAfterCompletion(synchronizations, TransactionSynchronization.STATUS_UNKNOWN); }
protected final void invokeAfterCompletion(List<TransactionSynchronization> synchronizations, int completionStatus) { TransactionSynchronizationUtils.invokeAfterCompletion(synchronizations, completionStatus); }
TransactionSynchronizationUtils.java
public static void invokeAfterCompletion(List<TransactionSynchronization> synchronizations, int completionStatus) { if (synchronizations != null) { for (TransactionSynchronization synchronization : synchronizations) { try { //调用synchronization的afterCompletion方法 //本博客以TransactionSynchronizationEventAdapter为例来看看如何实现 synchronization.afterCompletion(completionStatus); } catch (Throwable tsex) { logger.error("TransactionSynchronization.afterCompletion threw exception", tsex); } } } }
那么在例1.1中,synchronization是怎样来的呢?我们在TransactionSynchronizationEventAdapter的构造方法中打一个打断。
发现最终是调用UserServiceImpl的updateUserRequiresNew1方法时,构造了TransactionSynchronizationEventAdapter对象。
我们跟进代码。
AbstractApplicationContext.java
public void publishEvent(ApplicationEvent event) { publishEvent(event, null); }
protected void publishEvent(Object event, ResolvableType eventType) { Assert.notNull(event, "Event must not be null"); if (logger.isTraceEnabled()) { logger.trace("Publishing event in " + getDisplayName() + ": " + event); } // Decorate event as an ApplicationEvent if necessary ApplicationEvent applicationEvent; if (event instanceof ApplicationEvent) { applicationEvent = (ApplicationEvent) event; } else { applicationEvent = new PayloadApplicationEvent<Object>(this, event); if (eventType == null) { eventType = ResolvableType.forClassWithGenerics(PayloadApplicationEvent.class, event.getClass()); } } // Multicast right now if possible - or lazily once the multicaster is initialized if (this.earlyApplicationEvents != null) { this.earlyApplicationEvents.add(applicationEvent); } else { getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType); } // Publish event via parent context as well... if (this.parent != null) { if (this.parent instanceof AbstractApplicationContext) { ((AbstractApplicationContext) this.parent).publishEvent(event, eventType); } else { this.parent.publishEvent(event); } } }
SimpleApplicationEventMulticaster.java
public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) { ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event)); //遍历当前系统中所有的监听器 for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) { Executor executor = getTaskExecutor(); if (executor != null) { executor.execute(new Runnable() { @Override public void run() { invokeListener(listener, event); } }); } else { invokeListener(listener, event); } } }
遍历所有的监听器。那么监听器又是从哪里来的呢?带着疑问,我们再次回到registerTransactionalEventListenerFactory方法。在这个方法中注册了TransactionalEventListenerFactory工厂类,那这个工厂类又有什么作用呢?我们先来看TransactionalEventListenerFactory类,在这个类中有一个supportsMethod方法,如下:
public boolean supportsMethod(Method method) { return (AnnotationUtils.findAnnotation(method, TransactionalEventListener.class) != null); }
这个方法又是哪里调用的呢?只有一个地方调用,也就是EventListenerMethodProcessor的processBean方法,在这个方法中打一个断点。
发现竟然是在refresh()方法内的finishBeanFactoryInitialization()方法中调用。这个方法主要用于初始化所有剩余的单例Bean。
AbstractApplicationContext.java
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { // 这是Spring 3 新加的代码,为容器指定个转换服务(ConversionService) // 在对某些Bean属性进行转换时使用 if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) && beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) { LogUtils.info("finishBeanFactoryInitialization beanFactory constains conversionService"); beanFactory.setConversionService( beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)); } String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false); for (String weaverAwareName : weaverAwareNames) { getBean(weaverAwareName); } // 为了使类型匹配,停止使用临时的类加载器 beanFactory.setTempClassLoader(null); // 冻结所有的 bean 的定义,说明注册的 bean 定义将不被修改或者进一步的处理 beanFactory.freezeConfiguration(); // 初始化剩下的单实例(非惰性的) beanFactory.preInstantiateSingletons(); }
DefaultListableBeanFactory.java
public void preInstantiateSingletons() throws BeansException { if (this.logger.isDebugEnabled()) { this.logger.debug("Pre-instantiating singletons in " + this); } // Iterate over a copy to allow for init methods which in turn register new bean definitions. // While this may not be part of the regular factory bootstrap, it does otherwise work fine. List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames); // Trigger initialization of all non-lazy singleton beans... for (String beanName : beanNames) { // 获取指定名称的Bean 定义 RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); // Bean 不是抽象的,是单例模式的,且lazy-init属性配置为false if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { // 如果指定的名称的Bean是创建容器的Bean if (isFactoryBean(beanName)) { //FACTORY_BEAN_PREFIX="&",当Bean 名称前面加了&符号时,获取的是容器对象本身,而不是容器产生的Bean // 调用getBean 方法,触发Bean实例化,和依赖注入 final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName); // 标识是否需要预实例化 boolean isEagerInit; if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { // 一个匿名的内部类 isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() { @Override public Boolean run() { return ((SmartFactoryBean<?>) factory).isEagerInit(); } }, getAccessControlContext()); } else { isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factory).isEagerInit()); } if (isEagerInit) { // 调用getBean()方法,触发Bean实例化和依赖注入 getBean(beanName); } } else { getBean(beanName); } } } // Trigger post-initialization callback for all applicable beans... for (String beanName : beanNames) { Object singletonInstance = getSingleton(beanName); if (singletonInstance instanceof SmartInitializingSingleton) { final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance; if (System.getSecurityManager() != null) { AccessController.doPrivileged(new PrivilegedAction<Object>() { @Override public Object run() { smartSingleton.afterSingletonsInstantiated(); return null; } }, getAccessControlContext()); } else { smartSingleton.afterSingletonsInstantiated(); } } } }
到这里我又有疑问了,你怎么就知道smartSingleton是EventListenerMethodProcessor对象呢?EventListenerMethodProcessor又是怎样来的呢?
毫无疑问EventListenerMethodProcessor实现了SmartInitializingSingleton接口,因此preInstantiateSingletons方法的if (singletonInstance instanceof SmartInitializingSingleton) {…}这个判断条件肯定满足,但是EventListenerMethodProcessor又是在哪里被回到容器中去的呢?
在代码中搜寻,最后发现只有registerAnnotationConfigProcessors这个方法中被使用。这下好办了,在registerAnnotationConfigProcessors方法中打断点。
同样是在refresh()方法内的obtainFreshBeanFactory()方法中调用。
最终发现在解析component-scan标签元素时,如果容器中没有org.springframework.context.event.internalEventListenerProcessor的BeanDefinition,则注册EventListenerMethodProcessor的beanDefinition。因此在preInstantiateSingletons方法中,遍历所有的beanName时会找到EventListenerMethodProcessor处理器。下面我们来继续跟进afterSingletonsInstantiated方法。
EventListenerMethodProcessor.java
public void afterSingletonsInstantiated() { //获取容器中所有实现了EventListenerFactory接口的bean List<EventListenerFactory> factories = getEventListenerFactories(); String[] allBeanNames = this.applicationContext.getBeanNamesForType(Object.class); //遍历所有的实现了EventListenerFactory接口的beanName for (String beanName : allBeanNames) { //如果beanName不为空并且不以scopedTarget.开头 if (!ScopedProxyUtils.isScopedTarget(beanName)) { Class<?> type = this.applicationContext.getType(beanName); try { //处理bean processBean(factories, beanName, type); } catch (RuntimeException e) { throw new BeanInitializationException("Failed to process @EventListener " + "annotation on bean with name '" + beanName + "'", e); } } } }
显然TransactionalEventListenerFactory实现了EventListenerFactory接口。因此allBeanNames肯定有org.springframework.context.event.internalEventListenerProcessor值。
EventListenerMethodProcessor.java
protected void processBean(List<EventListenerFactory> factories, String beanName, final Class<?> type) { //获取beanName的真实类型,如果type是SpringProxy类或其子类,则获取beanName对应bean的真实类型 //如type是cglib 代理类型,则获取type的父类类型作为真实类型 Class<?> targetType = getTargetClass(beanName, type); if (!this.nonAnnotatedClasses.contains(targetType)) { final Set<Method> annotatedMethods = new LinkedHashSet<Method>(1); //获取EventListenerFactory所有的方法 Method[] methods = ReflectionUtils.getUniqueDeclaredMethods(targetType); for (Method method : methods) { //方法注解中没有配置EventListener注解,则直接略过。TransactionalEventListener注解和EventListener什么关系呢? //如图1.1一样,而findAnnotation方法不仅仅能得到方法上有没有配置EventListener注解, //还可以获取到方法上注解的注解上是否有EventListener注解。 EventListener eventListener = AnnotationUtils.findAnnotation(method, EventListener.class); if (eventListener == null) { continue; } for (EventListenerFactory factory : factories) { //调用EventListenerFactory的supportsMethod方法 if (factory.supportsMethod(method)) { //如果type是代理类型,则获取代理方法替换掉EventListenerFactory的原始方法 if (!type.equals(targetType)) { method = getProxyMethod(type, method); } //创建ApplicationListener监听器 ApplicationListener<?> applicationListener = factory.createApplicationListener(beanName, type, method); if (applicationListener instanceof ApplicationListenerMethodAdapter) { ((ApplicationListenerMethodAdapter)applicationListener) .init(this.applicationContext, this.evaluator); } //向容器中注册监听器 this.applicationContext.addApplicationListener(applicationListener); annotatedMethods.add(method); break; } } } if (annotatedMethods.isEmpty()) { this.nonAnnotatedClasses.add(type); if (logger.isTraceEnabled()) { logger.trace("No @EventListener annotations found on bean class: " + type); } } else { // Non-empty set of methods if (logger.isDebugEnabled()) { logger.debug(annotatedMethods.size() + " @EventListener methods processed on bean '" + beanName + "': " + annotatedMethods); } } } }
TransactionalEventListenerFactory.java
public class TransactionalEventListenerFactory implements EventListenerFactory, Ordered { private int order = 50; public void setOrder(int order) { this.order = order; } @Override public int getOrder() { return order; } @Override public boolean supportsMethod(Method method) { //方法上是否有TransactionalEventListener注解 return (AnnotationUtils.findAnnotation(method, TransactionalEventListener.class) != null); } @Override public ApplicationListener<?> createApplicationListener(String beanName, Class<?> type, Method method) { return new ApplicationListenerMethodTransactionalAdapter(beanName, type, method); } }
程序分析到这里,我们来总结一下监听器的由来。
- 在解析<tx:annotation-driven ></tx:annotation-driven>标签时,调用了registerTransactionalEventListenerFactory方法,向容器中注册了TransactionalEventListenerFactory事务事件监听器工厂。
- 在解析<context:component-scan base-package=“com.spring_101_200.test_181_190.test_181_commit_rollback_listener”></context:component-scan>标签时,调用了registerAnnotationConfigProcessors方法,注册了EventListenerMethodProcessor事件方法监听处理器。
- 在初始化所有剩余的单例Bean时调用afterSingletonsInstantiated方法对EventListenerFactory所有的方法进行遍历,对于所有配置了TransactionalEventListener注解的方法注册ApplicationListener监听器。
经过上面的分析,我相信大家对getApplicationListeners获取到所有的监听器中监听器的由来己经清楚了。
SimpleApplicationEventMulticaster.java
protected void invokeListener(ApplicationListener listener, ApplicationEvent event) { ErrorHandler errorHandler = getErrorHandler(); if (errorHandler != null) { try { listener.onApplicationEvent(event); } catch (Throwable err) { errorHandler.handleError(err); } } else { listener.onApplicationEvent(event); } }
ApplicationListenerMethodTransactionalAdapter.java
public void onApplicationEvent(ApplicationEvent event) { //如果当前线程中存在事务 if (TransactionSynchronizationManager.isSynchronizationActive()) { //创建TransactionSynchronizationEventAdapter对象 TransactionSynchronization transactionSynchronization = createTransactionSynchronization(event); //注册TransactionSynchronizationEventAdapter,也就是向当前线程synchronizations中添加值 TransactionSynchronizationManager.registerSynchronization(transactionSynchronization); } else if (this.annotation.fallbackExecution()) { if (this.annotation.phase() == TransactionPhase.AFTER_ROLLBACK) { logger.warn("Processing '" + event + "' as a fallback execution on AFTER_ROLLBACK phase."); } //直接发布事件 processEvent(event); } else { if (logger.isDebugEnabled()) { logger.debug("No transaction is running, skipping '" + event + "' for '" + this + "'"); } } }
private TransactionSynchronization createTransactionSynchronization(ApplicationEvent event) { return new TransactionSynchronizationEventAdapter(this, event, this.annotation.phase()); }
TransactionSynchronizationEventAdapter.java
private static class TransactionSynchronizationEventAdapter extends TransactionSynchronizationAdapter { private final ApplicationListenerMethodAdapter listener; private final ApplicationEvent event; private final TransactionPhase phase; public TransactionSynchronizationEventAdapter(ApplicationListenerMethodAdapter listener, ApplicationEvent event, TransactionPhase phase) { this.listener = listener; this.event = event; this.phase = phase; } @Override public void beforeCommit(boolean readOnly) { if (this.phase == TransactionPhase.BEFORE_COMMIT) { processEvent(); } } @Override public void afterCompletion(int status) { if (this.phase == TransactionPhase.AFTER_COMPLETION) { processEvent(); } else if (this.phase == TransactionPhase.AFTER_COMMIT && status == STATUS_COMMITTED) { processEvent(); } else if (this.phase == TransactionPhase.AFTER_ROLLBACK && status == STATUS_ROLLED_BACK) { //发布事件 processEvent(); } } @Override public int getOrder() { return this.listener.getOrder(); } protected void processEvent() { this.listener.processEvent(this.event); } }
ApplicationListenerMethodAdapter.java
public void processEvent(ApplicationEvent event) { Object[] args = resolveArguments(event); if (shouldHandle(event, args)) { Object result = doInvoke(args); if (result != null) { handleResult(result); } else { logger.trace("No result object given - no result to handle"); } } }
ApplicationListenerMethodAdapter.java
protected Object doInvoke(Object... args) { Object bean = getTargetBean(); ReflectionUtils.makeAccessible(this.bridgedMethod); try { return this.bridgedMethod.invoke(bean, args); } catch (IllegalArgumentException ex) { assertTargetBean(this.bridgedMethod, bean, args); throw new IllegalStateException(getInvocationErrorMessage(bean, ex.getMessage(), args), ex); } catch (IllegalAccessException ex) { throw new IllegalStateException(getInvocationErrorMessage(bean, ex.getMessage(), args), ex); } catch (InvocationTargetException ex) { // Throw underlying exception Throwable targetException = ex.getTargetException(); if (targetException instanceof RuntimeException) { throw (RuntimeException) targetException; } else { String msg = getInvocationErrorMessage(bean, "Failed to invoke event listener method", args); throw new UndeclaredThrowableException(targetException, msg); } } }
代码执行到这里,也不再跟进了,无非是通过反射方法调用来执行目标方法。
程序分析到这里我信息大家对TransactionSynchronization的使用及原理有了一定的理解。
- 在事务中调用applicationEventPublisher.publishEvent(new MyTransactionEvent(“XXX~~~”, 1))方法,先调用TransactionSynchronizationManager的isSynchronizationActive方法判断当前线程中是否存在事务。如果存在事务,则调用createTransactionSynchronization方法创建TransactionSynchronization对象存储到synchronizations中。
- 当事务提交或者回滚等操作时调用triggerXXX方法,此时会遍历所有存储在synchronizations中的TransactionSynchronization对象,并调用其相应的afterXXX方法,在afterXXX方法中会根据相应的status调用其相应的processEvent方法,来发布事件。
源码解析到这里,我相信大家对Spring事务这一块有了深刻的理解,但是确实,还有很多只可意会不可言传东西没有写出来,因为Spring源码确实太博大精深,在读MyBatis源码时,会觉得中规中矩,就是先解析XML文件,或者Mapper类,再将全局配置文件信息全部存储到Configuration对象中,再创建一个基于Mapper的JDK动态代理,在获取Mapper时,实际上是获取到Mapper的代理对象,再通过代理的invoke方法去封装请求参数,返回参数等,再根据配置参数该缓存的缓存,可能我觉得MyBatis中最巧妙之处是插件的源码实现,非常强大也非常的巧妙,但再来看Spring源码,每一个小的方法中,都可以看到其精妙,都考虑到很多的情况,就对于commit事务而言,我们只用了DataSourceTransactionManager来讲解,但是其他的像HibernateTransactionManager,JmsTransactionManager,JtaTransactionManager,RabbitTransactionManager等等,甚至是我们可以自定义,因此,对于Spring源码来说,我只能说是太博大精深来形容,甚至有个时候,我都庆幸能够遇到如此优秀的源码,并且每天使用她。好的,有兴趣的同学还是自己去下载源码来研读一翻,相信你有意想不到的收获。到这里,我们对Spring事务管理这一块的源码己经告一段落,下面我们来总结一下整个流程。
流程:
1)registerBeanDefinitionParser():在TxNamespaceHandler注册annotation-driven的解析器AnnotationDrivenBeanDefinitionParser 1)parse():AnnotationDrivenBeanDefinitionParser的解析方法 1)registerTransactionalEventListenerFactory():注册TransactionalEventListenerFactory 1)registerAutoProxyCreatorIfNecessary():向容器中注册AutoProxyCreator的beanDefinition,在本例中AutoProxyCreator指的是InfrastructureAdvisorAutoProxyCreator 2)configureAutoProxyCreator():配置事务相关代理 2)registerWithGeneratedName(sourceDef):注册AnnotationTransactionAttributeSource 3)registerTransactionManager():注册事务管理器 1)addPropertyValues("transactionManagerBeanName"):配置注入transactionManager 4)registerWithGeneratedName(interceptorDef):注册TransactionInterceptor 1)addPropertyValues("transactionAttributeSource"):配置注入AnnotationTransactionAttributeSource实例 5)registerBeanDefinition(txAdvisorBeanName, advisorDef):配置注册BeanFactoryTransactionAttributeSourceAdvisor 1)addPropertyValues("transactionAttributeSource"):配置注入AnnotationTransactionAttributeSource 2)addPropertyValues("adviceBeanName"):配置注入TransactionInterceptor 2)initializeBean():实例化bean 1)applyBeanPostProcessorsAfterInitialization():调用所有的BeanPostProcessor的postProcessAfterInitialization方法 1)getBeanPostProcessors():获取到所有的BeanPostProcessor处理器 2)调用其postProcessAfterInitialization方法 1)wrapIfNecessary():检查目标类,如UserServiceImpl是否需要被代理 1) getAdvicesAndAdvisorsForBean():获取所有对目标类或目标类方法拦截的增强器。 1) findEligibleAdvisors():获取所有对目标类或目标类方法拦截的增强器。 1)findCandidateAdvisors():获取系统中所有的增强器 2)findAdvisorsThatCanApply():找到能对目标类或目标方法增强的增强器 。 1)canApply():增强器能否增强目标类或方法 1)matches():切点是否匹配 1) getTransactionAttributeSource():获取到AnnotationTransactionAttributeSource 2)getTransactionAttribute():获取目标类或方法及接口方法或接口中是否配置了事务属性,如是否配置了@Transactional注解。 1)computeTransactionAttribute():获取事务属性 1)findTransactionAttribute():从方法或方法所在类或接口方法或接口方法所在接口中获取事务属性 1)determineTransactionAttribute():开始获取事务属性 1)parseTransactionAnnotation():解析事务注解@Transactional 1)getEnum("propagation"):获取propagation事务传播行为属性 2)getEnum("isolation"):获取数据库事务隔离级别属性 3)getNumber("timeout"):获取事务超时时间属性 4)getBoolean("readOnly"):获取事务只读属性 5)getQualifier("value"):获取事务管理器配置 6)getClassArray("rollbackFor"):获取回滚异常数组 7)getStringArray("rollbackForClassName"):获取回滚类名数组 8)getClassArray("noRollbackFor"):获取非回滚类数组 9)getStringArray("noRollbackForClassName"):获取非回滚类名数组 2) createProxy():如果增强器不为空,则创建动态代理 3)invoke():动态代理调用 1)getInterceptorsAndDynamicInterceptionAdvice():获取增强器 1)getInterceptors():获取拉增强器的所有拦截器 1)getAdvice():根据BeanFactoryTransactionAttributeSourceAdvisor的adviceBeanName属性获取到TransactionInterceptor 2)proceed():调用拦截器的proceed()方法 1)invoke():调用TransactionInterceptor的invoke方法 1)invokeWithinTransaction():调用TransactionInterceptor的invokeWithinTransaction方法 1)getTransactionAttribute():获取事务属性 2)determineTransactionManager():获取事务管理器,本例中是DataSourceTransactionManager 3)createTransactionIfNecessary():获取事务信息 1)getTransaction():获取事务Status 1)doGetTransaction():获取DataSourceTransactionObject对象 2)isExistingTransaction():当前线程中己经存在事务 1)handleExistingTransaction():当前线程中己经存在事务处理 1)PropagationBehavior()==PROPAGATION_NEVER:如果事务的传播行为是PROPAGATION_NEVER,抛出异常 2)PropagationBehavior()==PROPAGATION_NOT_SUPPORTED:如果事务的传播行为是PROPAGATION_NOT_SUPPORTED 1)suspend(transaction):挂起当前事务 1)doSuspendSynchronization():激活TransactionSynchronization的suspend方法 1)suspend():激活TransactionSynchronization的suspend方法 2)clearSynchronization():清除对象synchronizations中的TransactionSynchronization 2)doSuspend(transaction):真正挂起事务 1)unbindResource():解绑dataSource 3)doResumeSynchronization():抛出RuntimeException或Error则恢复synchronizations中的TransactionSynchronization 1)resume():恢复synchronizations中的TransactionSynchronization 2)registerSynchronization():重新将添加TransactionSynchronization到synchronizations中 2)如果当前线程中没有事务,或事务没有激活,则直接返回null 2)prepareTransactionStatus():准备事务状态 3)PropagationBehavior()==PROPAGATION_REQUIRES_NEW:如果事务的传播行为是PROPAGATION_REQUIRES_NEW 1)suspend(transaction):挂起当前事务 2)prepareTransactionStatus():准备事务状态 4)PropagationBehavior()==PROPAGATION_REQUIRES_NEW:如果当前的事务传播行为是PROPAGATION_REQUIRES_NEW 1)suspend(transaction):挂起当前线程中的事务 2)newTransactionStatus():创建新的事务状态 3)doBegin():开启新事务 4)prepareSynchronization():初始化当前线程中的事务名称,隔离级别,是否激活,初始化synchronizations 5)PropagationBehavior()==PROPAGATION_SUPPORTS OR PROPAGATION_REQUIRED:如果当前的事务传播行为是PROPAGATION_SUPPORTS 或 OR 1)prepareTransactionStatus():准备事务状态 3)getTimeout() < TIMEOUT_DEFAULT:事务超时,抛出异常 4)PropagationBehavior()==PROPAGATION_MANDATORY:如果事务的传播行为是PROPAGATION_MANDATORY,抛出异常 5)getPropagationBehavior()==PROPAGATION_REQUIRED || PropagationBehavior()==PROPAGATION_REQUIRES_NEW || PropagationBehavior()==PROPAGATION_NESTED:如果事务的传播行为是PROPAGATION_REQUIRED或PROPAGATION_REQUIRES_NEW或PROPAGATION_NESTED 1)suspend(null):空挂起 2)newTransactionStatus():创建新的事务状态 3)doBegin():开启事务 4)prepareSynchronization():初始化当前线程中的事务名称,隔离级别,是否激活,初始化synchronizations 5)如果以上情况都不是,则: 1)prepareTransactionStatus():初始化当前线程中的事务名称,隔离级别,是否激活,初始化synchronizations 2)prepareTransactionInfo():根据指定的属性与status准备一个TransactionInfo 1)bindToThread():将事务信息绑定到当前线程 4)proceedWithInvocation():继续调用拦截器链中的方法 5)completeTransactionAfterThrowing():抛出异常回滚 1)rollback():判断是否回滚默认的依据是抛出的异常是否是 RuntimeException 或 Error 2)commit():不符合事务回滚条件,提交事务 6)cleanupTransactionInfo():清理事务信息 1)restoreThreadLocalStatus():恢复旧的事务信息 2)transactionInfoHolder.set(this.oldTransactionInfo):将旧的事务信息赋值给当前线程的事务信息持有者 7)commitTransactionAfterReturning():提交事务 1)commit():提交事务 1)processRollback():事务链中己经被标记回滚,那么不会尝试提交事务,直接回滚 2)processCommit():真正的提交事务 1)prepareForCommit():预留,为第三方包提交前做准备,如Hibernate 2)triggerBeforeCommit():添加TransactionSynchronization中对应的方法调用 3)triggerBeforeCompletion():添加TransactionSynchronization中对应的方法调用 4)hasSavepoint():如果有保存点 1)releaseHeldSavepoint():释放保存点 5)isNewTransaction():如果是独立事务 1)doCommit():如果是独立的事务,直接提交 1)con.commit():提交事务 6)thows UnexpectedRollbackException: 1) triggerAfterCompletion():添加TransactionSynchronization中对应的方法调用 7)throws TransactionException: 1)triggerAfterCompletion():添加TransactionSynchronization中对应的方法调用 8)throws RuntimeException(): 1)doRollbackOnCommitException():回滚事务或设置全局事务回滚标识 9)finally 1)cleanupAfterCompletion():清理事务信息 1) clearSynchronization():清理掉synchronizations 2)置空当前线程的事务名,事务只读,隔离级别和事务激活为false 2)doCleanupAfterCompletion(): 1)unbindResource():解绑dataSource 2)AutoCommit(true):autoCommit置为true 3)resetConnectionAfterTransaction():重置数据库连接 4)releaseConnection():如果当前事务时独立的新创建的事务则在事务完成时释放数据库连接 3)resume():恢复之前挂起的 1)doResume(transaction, suspendedResources): 1)bindResource:绑定之前的数据库资源 2)doResumeSynchronization():恢复之前的TransactionSynchronization
本文的github地址是
https://github.com/quyixiao/spring_tiny