Spring-事务源码分析

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
- 异常属性:
	RuntimeError的子类默认进行回滚
	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;
			}
		}
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值