Spring-事务源码分析
1、事务概念
1、什么是事务?
保证业务操作完整性的一种数据库机制(Driver驱动)
2、事务的特性
ACID
A 原子性:多次操作要么一起成功,要么一起失败
C 一致性:事务开始时数据的状态和事务结束时数据的状态是一致的
I 隔离性:多个事务之间不能相互影响,(并发条件下)
D 持久性:事务操作的结果,持久化到数据库中
3、事务的处理
1、单机版 Connection
Mybatis SqlSession(Connection)
connection.setAutoCommit(false);
connection.commit();
connection.rollback()
JavaEE 分层开发Servlet(Transtion Connection) Dao(Connection)如何保证
Server Dao共同一个Connection ------------------------------------>(ThreadLocal)
2、分布式事务
采用Java EE JTA
EJB3.X
4、Spring控制事务
1、核心要点:
通过Aop创建事务
2、控制事务的2种编程方式
(1)编码TransactionTemplate(Template采用模板设计模式)目前不采用这种方式
(2)声明式事务(Aop Proxy代理设计模式通过配置文件或者注解的方式控制事务)推荐
TransactionTemplate代码编程示例
public class TransactionTemplateTest {
public static void main(String[] args) {
TransactionTemplate template = new TransactionTemplate();
template.execute(new TransactionCallback<Object>() {
@Override
public Object doInTransaction(TransactionStatus status) {
//service代码
return null;
}
});
}
}
2、事务的属性
事务属性:
1、隔离属性isolation
2、传播属性Propagation
3、超时数据Timeout
4、只读属性ReadOnly
5、异常属性 Exception
- 隔离属性:
ISOLATION,默认值为ISOLATION_DEFAULT,由数据库默认设置传播属性,作为Spring事务的默认
属性。
READ_UNCOMMTED:读取另一个事务未提交的数据
READ_COMMITED 读取已提交的数据
REPEATABLE 不可重复读
SERILIZABLE
- 传播属性
PROPAGATION 解决事务嵌套问题
REQUIRED 当前的这个业务方法外部没有事务开启事务 外部存在事务则融合
REQUIRED_NEW 当前的这个业务方法外部没有事务开启事务,外部存在事务挂起外部事务开启新的事务,执行新的事务之后再还原外部事务的执行
MANDATORY 当前的这个业务方法 外部必须存在事务
NEVER 当前的业务方法外部一定不能存在事务
SUPPORTS 当前的这个业务方法 外部没有事务则不开启事务,外部存在事务则融合
NOT_SUPPORTED 当前的这个业务方法 外部没有事务则不开启事务,外部存在事务则抛异常
NESTED 内嵌事务 savePoint
- 超时属性:
TIMEOUT超时属性通过超时属性设置本事务最长的等待时间-1,由数据库底层决定等待时间
- 只读属性:
READONLY:设置属性为只读属性,提高事务运行效率,默认为false
- 异常属性:
Runtime和Error的子类默认进行回滚
Exception及其子类,默认是进行提交的
Spring封装了一个实体TransactionDefinition,描述事务的属性
3、事务的开发
3.1、基于XMl配置文件形式
原始类
//实体类
public class User {
private Integer id;
private String name;
private String password;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", password='" + password + '\'' +
'}';
}
}
//Service接口
public interface UserService {
public void register(User user);
}
//Service实现类
@Service
public class UserServiceImpl implements UserService{
@Autowired
private UserDao userDao;
@Override
public void register(User user) {
userDao.save(user);
}
}
public interface UserDao {
public void save(User user);
}
@Repository
public class UserDaoImpl implements UserDao {
//封装了connection
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public void save(User user) {
jdbcTemplate.update("insert into user(name,password) values (?,?)", user.getName(), user.getPassword());
}
}
配置文件
<?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:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
https://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--开启注解扫描-->
<context:component-scan base-package="com.xiaohe.tx"/>
<!--JDBCTemplate-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--连接池-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/hezb?useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
<!--DataSourceTransactionManager 事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!---->
<tx:advice id="transactionInterceptor" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="register" isolation="DEFAULT" propagation="REQUIRED"/>
<tx:method name="modify*"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="pc" expression="execution(* com.xiaohe.tx.xml.UserServiceImpl.*(..))"/>
<aop:advisor advice-ref="transactionInterceptor" pointcut-ref="pc"/>
</aop:config>
</beans>
3.2、基于注解形式
原始类
public interface UserService {
public void register(User user);
public void modify(User user);
}
@Service
public class UserServiceImpl implements UserService, ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@Autowired
private UserDao userDao;
@Override
@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT)
public void register(User user) {
System.out.println("register invoke");
UserService userService = applicationContext.getBean("userServiceImpl", UserService.class);
userService.modify(user);
userDao.save(user);
}
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW,isolation = Isolation.DEFAULT)
public void modify(User user) {
System.out.println(" modify invoke");
userDao.update(user);
}
}
public interface UserDao {
public void save(User user);
public void update(User user);
}
@Repository
public class UserDaoImpl implements UserDao {
//封装了connection
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public void save(User user) {
jdbcTemplate.update("insert into user(name,password) values (?,?)", user.getName(), user.getPassword());
}
@Override
public void update(User user) {
jdbcTemplate.update("update user set name=?,password=? where id=?",user.getName(),user.getPassword(),user.getId());
}
}
配置类AppConfig
@Configuration
@ComponentScan("com.xiaohe.tx.annocation")
@EnableTransactionManagement
public class AppConfig {
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource){
JdbcTemplate jdbcTemplate = new JdbcTemplate();
jdbcTemplate.setDataSource(dataSource);
return jdbcTemplate;
}
@Bean
public DataSource dataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/hezb?useSSL=false");
dataSource.setUsername("root");
dataSource.setPassword("123456");
return dataSource;
}
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource){
DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
dataSourceTransactionManager.setDataSource(dataSource);
return dataSourceTransactionManager;
}
}
测试类
public class MainTest {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = (UserService) context.getBean("userServiceImpl");
User user = new User();
user.setName("xiaohe");
user.setPassword("123234455");
userService.register(user);
}
}
4、事务的源码
1、BeanPostProcessor创建代理
2、调用Service.xxxx方法过程中,动态运行时原始功能+额外功能整合在一起
4.1、代理的创建
事务代理的创建其实和AOP代理的创建思路是一样的,其主要的主要@EnableTransactionManagement
底层采用@Import(TransactionManagementConfigurationSelector.class)的方式注册Bean,
分析TransactionManagementConfigurationSelector可以知道这个类其实是ImportSelector的子类,会调用selectImports进行Bean的注册
TransactionManagementConfigurationSelector
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
@Override
protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
//一般采用PROXY,所以走这个方式
case PROXY:
return new String[] {AutoProxyRegistrar.class.getName(),
ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
return new String[] {determineTransactionAspectClass()};
default:
return null;
}
}
private String determineTransactionAspectClass() {
return (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader()) ?
TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME :
TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME);
}
}
分析AutoProxyRegistrar通过BeanPostProcessor进行代理的创建
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean candidateFound = false;
//1、解析@EnableTransactionManagement的属性
Set<String> annTypes = importingClassMetadata.getAnnotationTypes();
for (String annType : annTypes) {
//2、获取注解的属性
AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
if (candidate == null) {
continue;
}
Object mode = candidate.get("mode");
Object proxyTargetClass = candidate.get("proxyTargetClass");
if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
Boolean.class == proxyTargetClass.getClass()) {
candidateFound = true;
if (mode == AdviceMode.PROXY) {
//注册事务控制的BeanPostProcessor InfrastructureAdvisorAutoProxyCreator.class
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
if ((Boolean) proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
return;
}
}
}
}
if (!candidateFound && logger.isInfoEnabled()) {
String name = getClass().getSimpleName();
}
}
}
由类关系图看出InfrastructureAdvisorAutoProxyCreator为BeanPostProcessor的子类并且为InstantiationAwareBeanPostProcessor默认调用postProcessAfterInitialization()
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
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;
}
接下来的代码和Spring Aop一样,进行代理的创建,这个过程要知道这个postProcessAfterInitialization回调的过程是在对象创建的初始化过程进行回调的。
分析ProxyTransactionManagementConfiguration进行代理属性的解析
@Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
advisor.setTransactionAttributeSource(transactionAttributeSource());
advisor.setAdvice(transactionInterceptor());
if (this.enableTx != null) {
advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
}
return advisor;
}
//解析注解
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
return new AnnotationTransactionAttributeSource();
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionInterceptor transactionInterceptor() {
TransactionInterceptor interceptor = new TransactionInterceptor();
interceptor.setTransactionAttributeSource(transactionAttributeSource());
if (this.txManager != null) {
interceptor.setTransactionManager(this.txManager);
}
return interceptor;
}
}
public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {
this.publicMethodsOnly = publicMethodsOnly;
if (jta12Present || ejb3Present) {
this.annotationParsers = new LinkedHashSet<>(4);
this.annotationParsers.add(new SpringTransactionAnnotationParser());
//这是Spring处理分布式事务
if (jta12Present) {
this.annotationParsers.add(new JtaTransactionAnnotationParser());
}
if (ejb3Present) {
this.annotationParsers.add(new Ejb3TransactionAnnotationParser());
}
}
else {
//一般采用SpringTransactionAnnotationParser()进行解析
this.annotationParsers = Collections.singleton(new SpringTransactionAnnotationParser());
}
}
以上是代理的创建以及注解的解析逻辑
4.2、在Service运行过程中,原始功与事务切面的整合
以下是我们Debug过程
执行代理的invoke()方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
//切面目标类
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
//执行
retVal = invocation.proceed();
}
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
retVal = proxy;
}
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()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
proceed()
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;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
return proceed();
}
}
else {
//一般事务会走这个方法
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
invoke()
public Object invoke(MethodInvocation invocation) throws Throwable {
//原始类
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
//执行事务方法
return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
}
invokeWithinTransaction()执行事务的方法
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
final InvocationCallback invocation) throws Throwable {
//1、获取对应方法上对象属性的工具类
TransactionAttributeSource tas = getTransactionAttributeSource();
//2、封装了事务属性TransactionAttribute是TransactionDefinition的子类
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
//3、事务管理器 DataSourcetransactionManage,我们在配置文件中配置的或者xml里面配置的
final PlatformTransactionManager tm = determineTransactionManager(txAttr);
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
//创建事务,一般处理
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
Object retVal;
try {
//目标方法执行,具体 UserServiceImpl.register()
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// 事务回滚
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
//把oldTransationInfo还原到ThreadLocal恢复老的事务
cleanupTransactionInfo(txInfo);
}
commitTransactionAfterReturning(txInfo);
return retVal;
}
else {
final ThrowableHolder throwableHolder = new ThrowableHolder();
try {
Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr, 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.
throwableHolder.throwable = ex;
return null;
}
}
finally {
cleanupTransactionInfo(txInfo);
}
});
if (throwableHolder.throwable != null) {
throw throwableHolder.throwable;
}
return result;
}
catch (ThrowableHolderException ex) {
throw ex.getCause();
}
catch (TransactionSystemException ex2) {
if (throwableHolder.throwable != null) {
logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
ex2.initApplicationException(throwableHolder.throwable);
}
throw ex2;
}
catch (Throwable ex2) {
if (throwableHolder.throwable != null) {
logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
}
throw ex2;
}
}
}