引言
概述: AOP系列文章:
【1】Spring Aop初始化源码分析
【2】Spring AOP创建代理对象源码解析
【3】Spring AOP 链式调用过程源码解析
【4】Spring 事务执行过程源码解析
1 工程
1.1 数据库
CREATE TABLE `t_student` (
`c_id` int(11) NOT NULL AUTO_INCREMENT,
`c_name` varchar(255) DEFAULT NULL,
`c_age` int(12) DEFAULT NULL,
PRIMARY KEY (`c_id`)
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8;
1.2 pom
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<spring.version>5.2.8.RELEASE</spring.version>
</properties>
<dependencies>
<!--上下文-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<!--切面-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<!--事务-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<!--jdbc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.20</version>
</dependency>
<!-- 日志相关依赖 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.10</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.1.2</version>
</dependency>
<!--测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
</dependency>
<!--数据库-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.44</version>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
</dependencies>
1.3 SpringConfig
@Configuration
@EnableTransactionManagement
public class SpringConfig {
//创建数据源
@Bean
public DataSource dataSource() throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser("root");
dataSource.setPassword("123456");
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
return dataSource;
}
/**
* JDBC
*/
@Bean
public JdbcTemplate jdbcTemplate() throws PropertyVetoException{
return new JdbcTemplate(dataSource());
}
/**
* 配置事务管理器
*/
@Bean
public TransactionManager platformTransactionManager(DataSource dataSource) throws PropertyVetoException {
return new DataSourceTransactionManager(dataSource);
}
}
1.4 Service
public interface StudentService {
void insertStudent();
}
@Service
public class StudentServiceImpl implements StudentService {
@Autowired
private JdbcTemplate jdbcTemplate;
@Transactional
@Override
public void insertStudent() {
String sql = "insert into `t_student` (c_name, c_age) values(?,?)";
jdbcTemplate.update(sql, "张三", 18);
}
}
1.5 Test
public class RoshTest {
@Test
public void mainTest(){
AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext("com.rosh");
StudentService studentService = applicationContext.getBean(StudentService.class);
studentService.insertStudent();
}
}
1.6 运行
2 @EnableTransactionManagement 解析
作用: 开启事务。
2.1TransactionManagementConfigurationSelector
2.2 AutoProxyRegistrar
描述: 该类作向ioc中加入事务执行入口类InfrastructureAdvisorAutoProxyCreator.class,当bean实例化时进行后置加强。
2.3 ProxyTransactionManagementConfiguration
描述: 事务核心类,事务其实属于aop的一种典型实现,所以事务加强也有相应的pointcut和advice。
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {
/**
* 创建事务切面,advisor(pointcut advice)
*/
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
//设置属性
advisor.setTransactionAttributeSource(transactionAttributeSource);
//设置advice
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();
}
/**
* advice
*/
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) {
//创建事务切面
TransactionInterceptor interceptor = new TransactionInterceptor();
//设置事务处理器
interceptor.setTransactionAttributeSource(transactionAttributeSource);
//设置事务管理器
if (this.txManager != null) {
interceptor.setTransactionManager(this.txManager);
}
return interceptor;
}
}
切点:
描述: 是切点就有类匹配和方法匹配,TransactionAttributeSourcePointcut事务切点主要核心是方法匹配,类匹配没怎么干事。
描述: 匹配核心源码如下,首先必须是public , 匹配方法上是否带有Transactional注解,最后匹配类上是否带有Transactional注解。
@Nullable
protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
// Don't allow no-public methods as required.
/**
* 【1】 不是public方法不生成代理
*/
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;
}
// The method may be on an interface, but we need attributes from the target class.
// If the target class is null, the method will be unchanged.
/**
* 【2】 获取原始方法
*/
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
// First try is the method in the target class.
/**
* 【3】 方法匹配,找@Transactional注解,并且把注解属性封装成TransactionAttribute对象
*/
TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
if (txAttr != null) {
return txAttr;
}
// Second try is the transaction attribute on the target class.
/**
* 【4】 如果方法上没有注解,则判断类上是否有注解
*/
txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}
if (specificMethod != method) {
// Fallback is to look at the original method.
txAttr = findTransactionAttribute(method);
if (txAttr != null) {
return txAttr;
}
// Last fallback is the class of the original method.
txAttr = findTransactionAttribute(method.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}
}
return null;
}
advice
advice: 事务加强方法
@Nullable
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
final InvocationCallback invocation) throws Throwable {
// If the transaction attribute is null, the method is non-transactional.
//获取事务属性
TransactionAttributeSource tas = getTransactionAttributeSource();
/**
* 【1】 获取方法相关的事务属性(方法匹配pointcut过程)
*/
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
/**
* 【2】 获取事务管理器
*/
final TransactionManager tm = determineTransactionManager(txAttr);
if (this.reactiveAdapterRegistry != null && tm instanceof ReactiveTransactionManager) {
ReactiveTransactionSupport txSupport = this.transactionSupportCache.computeIfAbsent(method, key -> {
if (KotlinDetector.isKotlinType(method.getDeclaringClass()) && KotlinDelegate.isSuspend(method)) {
throw new TransactionUsageException(
"Unsupported annotated transaction on suspending function detected: " + method +
". Use TransactionalOperator.transactional extensions instead.");
}
ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(method.getReturnType());
if (adapter == null) {
throw new IllegalStateException("Cannot apply reactive transaction to non-reactive return type: " +
method.getReturnType());
}
return new ReactiveTransactionSupport(adapter);
});
return txSupport.invokeWithinTransaction(
method, targetClass, invocation, txAttr, (ReactiveTransactionManager) tm);
}
PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
//获取jointPoint
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
// Standard transaction demarcation with getTransaction and commit/rollback calls.
/**
* 【3】 开启事务
*/
TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);
Object retVal;
try {
// This is an around advice: Invoke the next interceptor in the chain.
// This will normally result in a target object being invoked.
/**
* 【4】 方法调取
*/
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// target invocation exception
/**
* 【5】 回滚
*/
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
cleanupTransactionInfo(txInfo);
}
if (retVal != null && vavrPresent && VavrDelegate.isVavrTry(retVal)) {
// Set rollback-only in case of Vavr failure matching our rollback rules...
TransactionStatus status = txInfo.getTransactionStatus();
if (status != null && txAttr != null) {
retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
}
}
/**
* 【7】 提交
*/
commitTransactionAfterReturning(txInfo);
return retVal;
}
3 Debug
3.1 修改代码
3.2 代理对象的创建
描述: 流程和aop一样,在studentServiceImpl实例后置加强时,用所有的advisor匹配当前类、方法,获取当前类有效的advisors,如果advisors不为空,那么创建代理对象,如果当前对象是接口实现类那么使用jdk,否则使用cglib,并把proxyFactory、当前匹配advisors存入代理对象中。
3.3 事务执行
结果:
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/15089.html