上次我们说过aop的源码,这次我们将解析事务的源码解析,我们都知道事务是交由spring管理的。也清楚事务是基于aop实现的。我们从声明式注解来解析。
代码
配置类
package com.gl.config;
import com.mysql.cj.jdbc.MysqlDataSourceFactory;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.mybatis.spring.SqlSessionFactoryBean;
import com.mysql.cj.jdbc.MysqlDataSource;
/**
* [TODO]
*
* @author gl
* @version V1.7
* @date 2024/4/11 15:03
*/
@ComponentScan("com.gl")//
@Configuration
@EnableTransactionManagement
@MapperScan("com.gl.mapper")
public class AppConfig {
@Bean
public MysqlDataSource dataSource(){
MysqlDataSource dataSource = new MysqlDataSource();
dataSource.setUrl("jdbc:mysql://localhost:3306/gl_dys_msme?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&autoReconnect=true&allowMultiQueries=true&rewriteBatchedStatements=true");
dataSource.setPassword("123456");
dataSource.setUser("root");
return dataSource;
}
@Bean("sqlSessionFactory")
public SqlSessionFactoryBean sqlSessionFactoryBean(){
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource());
sqlSessionFactoryBean.setMapperLocations(new ClassPathResource("com/gl/mapper/SysUserMapper.xml"));
return sqlSessionFactoryBean;
}
@Bean
public DataSourceTransactionManager dataSourceTransactionManager(){
DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
dataSourceTransactionManager.setDataSource(dataSource());
return dataSourceTransactionManager;
}
}
重要注解:@EnableTransactionManagement
service
@Service
public class SysUserServiceImpl implements SysUserService{
@Autowired
private SysUserMapper sysUserMapper;
@Override
@Transactional(propagation =Propagation.REQUIRED)
public void save() {
SysUser sysUser = new SysUser();
sysUser.setId(64);
sysUser.setName("das");
sysUserMapper.save(sysUser);
System.out.println(1/0);
}
}
测试类
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext("com");
SysUserService userService =(SysUserService) applicationContext.getBean("sysUserServiceImpl");
userService.save();
执行结果
可以看到spring执行事物的过程,首先先关闭自动提交事务,之后由于异常进行了事物会滚。
源码
从EnableTransactionManagement注解现在理解事务中用到的相关类。
@Import(TransactionManagementConfigurationSelector.class)
查看TransactionManagementConfigurationSelector的实现
protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:
// 默认是PROXY
//注册InfrastructureAdvisorAutoProxyCreator,才可以Bean进行AOP 实现后置处理器
return new String[] {AutoProxyRegistrar.class.getName(),
//切面类 通知 切点
ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
// 表示不用动态代理技术,用ASPECTJ技术,比较麻烦了
return new String[] {determineTransactionAspectClass()};
default:
return null;
}
}
这里会将两个重要的类交给spring管理
AutoProxyRegistrar
ProxyTransactionManagementConfiguration
AutoProxyRegistrar
首先进入AutoProxyRegistrar中来看他的作用
实现了ImportBeanDefinitionRegistrar类的registerBeanDefinitions方法。众所周知,这是在bean初始化前进行数据准备。并且后续会根据注册的beanName进行bean的初始化。那么我们来看看AutoProxyRegistrar注册了哪些bean。
if (mode == AdviceMode.PROXY) {
// 注册InfrastructureAdvisorAutoProxyCreator,才可以Bean进行AOP internalAutoProxyCreator
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
if ((Boolean) proxyTargetClass) {
// 设置InfrastructureAdvisorAutoProxyCreator的proxyTargetClass为true
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
return;
}
}
public static BeanDefinition registerAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
//判断registry是否已存在AUTO_PROXY_CREATOR_BEAN_NAME
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
//获取BeanDefinition
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
//谁的升级顺序高就实例化谁
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
以上会将InfrastructureAdvisorAutoProxyCreator类注册并在容器初始化时将该类进行初始化。
beanDefinition的详细数据
org.springframework.aop.config.internalAutoProxyCreator -> {RootBeanDefinition@1781}
"Root bean: class [org.springframework.aop.framework.autoproxy.InfrastructureAdvisorAutoProxyCreator];
scope=; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true;
primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null"
然后我们来看看InfrastructureAdvisorAutoProxyCreator 的作用
InfrastructureAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator
abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware
可以看到InfrastructureAdvisorAutoProxyCreator其实是实现继承了bean的后置处理器。那么我们来看看后置处理器的实现。
/** 正常进行AOP的地方
*/
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
//判断是否已经bean是否已经Aop,
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
我们发现这其实就是正常aop执行的地方。
那么我们现在可以知道第一个类AutoProxyRegistrar的作用。
注册了InfrastructureAdvisorAutoProxyCreator的配置,容器初始化时进行初始化。并作为后置处理器。那么其实在每个类初始化时都执行该后置处理器,那么执行这个后置处理器时会查到切面类advisor,然后判断对初始化的类是否需要增强。
其实这里将这个类作为初始化。是因为当我们没有引入aop时,依旧可以执行aop的相关逻辑。那这时候有人问,如果我们引入了aop那他岂不是要执行两次aop逻辑。其实不是的。我们看下这正常aop和事务aop引入的后置处理器。
正常aop后置处理器:
事务aop后置处理器:
可以看到两个后置处理器在初始化时beanName是一样的"org.springframework.aop.config.internalAutoProxyCreator"。
这里可以看出他们都是AbstractAdvisorAutoProxyCreator的子类。
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
这里会判断大小然后实例化具体的Bean。也就是说在spring容器中只会有一个aop的后置处理器存在。在aop最后会初始化[org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator],因为AnnotationAwareAspectJAutoProxyCreator 值是最大的最底层的。
总结:
InfrastructureAdvisorAutoProxyCreator作用当没有aop的时候,由它来作为后置处理器执行aop。
疑问:
是不是只使用@EnableTransactionManagement注解,就不用使用@EnableAspectJAutoProxy注解。
不是的,因为@EnableTransactionManagement 查询不到自定义的切面。所以不会执行自定义切面类。
ProxyTransactionManagementConfiguration
下面我们开始解析ProxyTransactionManagementConfiguration类。
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
//internalTransactionAdvisor 解析将 放到容器中
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
//继承 Advisor 切面
// TransactionInterceptor transactionInterceptor; 通知 执行invoke方法 即事务
// TransactionAttributeSourcePointcut 实现了MethodMatcher接口 和 pointcut 切点 用于在初始化的时候 匹配切点 需要aop的方法和类
// TransactionAttributeSourcePointcut 用于切点
// transactionAttributeSource解析 事务注解
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
advisor.setTransactionAttributeSource(transactionAttributeSource);
advisor.setAdvice(transactionInterceptor);
if (this.enableTx != null) {
advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
}
return advisor;
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
//解析事务注解属性
public TransactionAttributeSource transactionAttributeSource() {
// AnnotationTransactionAttributeSource中定义了一个Pointcut
// 并且AnnotationTransactionAttributeSource可以用来解析@Transactional注解,并得到一个RuleBasedTransactionAttribute对象
return new AnnotationTransactionAttributeSource();
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
//TransactionInterceptor 继承advice 通知
public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) {
//TransactionInterceptor 执行 invoke
TransactionInterceptor interceptor = new TransactionInterceptor();
interceptor.setTransactionAttributeSource(transactionAttributeSource);
if (this.txManager != null) {
interceptor.setTransactionManager(this.txManager);
}
return interceptor;
}
}
会发现ProxyTransactionManagementConfiguration是将三个类方法容器并且BeanFactoryTransactionAttributeSourceAdvisor 依赖另外两个类。
BeanFactoryTransactionAttributeSourceAdvisor
TransactionAttributeSource
TransactionInterceptor
TransactionAttributeSource
先说简单的TransactionAttributeSource。他的一个方法获取事务属性,其实里面就是包含事务注解的相关配置
TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass);
protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
Propagation propagation = attributes.getEnum("propagation");
rbta.setPropagationBehavior(propagation.value());
Isolation isolation = attributes.getEnum("isolation");
rbta.setIsolationLevel(isolation.value());
rbta.setTimeout(attributes.getNumber("timeout").intValue());
String timeoutString = attributes.getString("timeoutString");
Assert.isTrue(!StringUtils.hasText(timeoutString) || rbta.getTimeout() < 0,
"Specify 'timeout' or 'timeoutString', not both");
rbta.setTimeoutString(timeoutString);
rbta.setReadOnly(attributes.getBoolean("readOnly"));
rbta.setQualifier(attributes.getString("value"));
rbta.setLabels(Arrays.asList(attributes.getStringArray("label")));
List<RollbackRuleAttribute> rollbackRules = new ArrayList<>();
for (Class<?> rbRule : attributes.getClassArray("rollbackFor")) {
rollbackRules.add(new RollbackRuleAttribute(rbRule));
}
for (String rbRule : attributes.getStringArray("rollbackForClassName")) {
rollbackRules.add(new RollbackRuleAttribute(rbRule));
}
for (Class<?> rbRule : attributes.getClassArray("noRollbackFor")) {
rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
}
for (String rbRule : attributes.getStringArray("noRollbackForClassName")) {
rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
}
rbta.setRollbackRules(rollbackRules);
return rbta;
}
以上可以将TransactionAttributeSource看作是获取事务注解的具体配置用的。
TransactionInterceptor
下面我们来看TransactionInterceptor的实现。
TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable
其中先来看我们比较熟悉的MethodInterceptor接口,想必有人已经忘了这个接口。我们复习一下
这个接口有一个invoke方法,它是aop执行通知的具体实现。那么我们看下TransactionInterceptor实现的invoke方法。
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("执行事务");
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
// Adapt to TransactionAspectSupport's invokeWithinTransaction...
//执行事务
return invokeWithinTransaction(invocation.getMethod(), targetClass, new CoroutinesInvocationCallback() {
@Override
@Nullable
public Object proceedWithInvocation() throws Throwable {
// 执行后续的Interceptor,以及被代理的方法 执行advisor的方法
return invocation.proceed(); // test() sql
}
@Override
public Object getTarget() {
return invocation.getThis();
}
@Override
public Object[] getArguments() {
return invocation.getArguments();
}
});
}
是的这也是执行事务的具体实现。
那么我们现在来看TransactionInterceptor的作用就是在aop时候来执行事务的,即对执行的service中的mapper方法进行增强。
BeanFactoryTransactionAttributeSourceAdvisor
我们再来看看BeanFactoryTransactionAttributeSourceAdvisor这个类的作用。
BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor
AbstractBeanFactoryPointcutAdvisor extends AbstractPointcutAdvisor implements BeanFactoryAware
我们其实从类名就可以猜出它是作为切面类的角色出现的。
来看看具体实现。
//切点 实现了 MethodMatcher和Pointcut
private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
@Override
@Nullable
protected TransactionAttributeSource getTransactionAttributeSource() {
return transactionAttributeSource;
}
};
包含一个TransactionAttributeSourcePointcut类型的属性。来看看他的实现。
TransactionAttributeSourcePointcut
TransactionAttributeSourcePointcut用到了transactionAttributeSource 这个类,就是我们上面解析属性的类。
TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut
abstract class StaticMethodMatcherPointcut extends StaticMethodMatcher implements Pointcut
abstract class StaticMethodMatcher implements MethodMatcher
实现MethodMatcher的matches方法。
@Override
public boolean matches(Method method, Class<?> targetClass) {
TransactionAttributeSource tas = getTransactionAttributeSource();
//存在事务注解
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}
方法就是判断service中的类有没有@Tansaction注解。其实就是找到连接点,即要代理的方法。
那么我们可以看到TransactionAttributeSourcePointcut的作用
找到要代理加强的方法。
再来看看BeanFactoryTransactionAttributeSourceAdvisor的作用其实就是一个切面类。再来回顾这个类的生成。
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
advisor.setTransactionAttributeSource(transactionAttributeSource);
advisor.setAdvice(transactionInterceptor);
有一个属性TransactionAttributeSourcePointcut切点、连接点
一个属性transactionAttributeSource 解析Transaction注解
一个属性transactionInterceptor 通知。
那么TransactionAttributeSourcePointcut其实就是一个切面类。
回顾一下aop的组成部分:
切面类、切点、连接点、通知。
总结
这次我们可以看到@EnableTransactionManagement注解的具体实现。以及怎么使用aop来实现事务的。其实主要是后置处理器实现事务在什么时候执行。切面类实现事务增强的具体逻辑。