自定义注解事务课程回顾

你们对事务的基本原理理解了没有,事务的整个原理,声明式事务的原理,就相当于我完全自动化的,他自动通过

扫包或者注解,给我进行实现的,这种方式我们都叫做声明式的,还是不够底层,封装的还不够好,今天就有点难度了,

所以你们待会要认真听一下,任何声明事务,他都是基于编程事务进行实现出来的,声明事务他分为两种,第一种我们

称为xml方式,xml方式你们可以这样去理解,加一个扫包范围,然后在这个扫包范围里面,你可以去开启一个事务,

有没有印象,我记得我那会我刚学Spring的时候,比如我在com.learn.service这个包下面,只要有get,save方法,

我们都会加事务,然后在这里还有一个注解版本的,那么我们今天讲个比较难的,就是以什么配置开头的,这种属于xml

方式,什么以add开头,以save开头的我就开启事务,以get开头的,我就不给他开启事务,这种配置比较老了,一般我们

记住啊,因为你们在今后的时候都会学到,比如举个例子,save*星号,update*星号,insert*星号,有没有印象,通过方法名

进行区分事务,还有一种事务你们是绝对用过的,叫做注解版本的,你们用过@Transaction注解没有,这是不是注解版本的,

然后我加到方法里面去的时候,我就表示方法开启这个事务,今天讲一下这个底层是怎么实现的,为什么我要加上一个注解,

能够帮我去做事务管理,有没有人能告诉我他的原理是什么,我们今天讲的有点难度,写代码量有点大,为什么在方法上加入

@Transaction注解的时候,他能够开启事务,你们要知道原理,我点进去,什么都没有,没有源代码,这个其实我告诉你们,

其实怎么做的呢,其实我们今天讲什么原理呢,就是我们自己写一个事务注解出来,然后实现@Transaction一模一样的功能,

完全一模一样的功能,但是我们可能没有时间玩,我们上课时间也有限,具体功能你们下课自己去玩一下,这个思路是我

自己想的,不是说我看过他源码怎么做,因为我不喜欢看别人源码,因为我不看你源码我也能实现你的效果,所以我在

这里讲一下,你们学任何技术的时候,别人代码怎么写的时候,我就抄过来,那就没意义,要有自己的一套思路,这就叫编程思想,

所以在这边,再说一句话,叫编程思想,今后我们的HashMap和HashSet,分布式事务框架,都是按照我们自己的思路写的,

和别人的代码写的有差别,但是最终都达到一个效果,那么今天我们同学可能也知道,我们今天要实现一个自定义注解出来,

实现他的一个效果,那么什么效果呢,比如我现在加一个注解,这个注解我自己写的,叫@ExtTrasaction注解,这个注解是我

自己写出来的,只要加上这个注解之后,那么我就可以在这个方法之前和之后做一个事务管理机制,不知道你们有没有用过

lcn框架没有,他在里面是不是有这样的一种功能,需要在发起方加入一个注解,要在发起方的方法上加一个注解,这个注解

可以解决一个分布式问题,是不是这样的,他使用的也是自定义注解,那他这个是怎么进行实现的呢,我们大致看一下源码

好吧
package com.learn.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

//事务注解 设置传播行为
@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface ExtTransaction {

}
package com.learn.transaction;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;

/**
 * 我们把事务utils改成原型模式
 * 就是一个线程安全的
 * 每个事务都是一个单独的实例
 * 这样就可以解决一个高并发的一个线程安全问题
 * 
 * @author Leon.Sun
 *
 */
//编程事务(需要手动begin 手动回滚 手都提交)
@Component
@Scope("prototype") // 每个事务都是新的实例 目的解决线程安全问题 多例子
public class TransactionUtils {

	// 全局接受事务状态
	private TransactionStatus transactionStatus;
	// 获取事务源
	@Autowired
	private DataSourceTransactionManager dataSourceTransactionManager;

	// 开启事务
	public TransactionStatus begin() {
		System.out.println("开启事务");
		transactionStatus = dataSourceTransactionManager.getTransaction(new DefaultTransactionAttribute());
		return transactionStatus;
	}

	// 提交事务
	public void commit(TransactionStatus transaction) {
		System.out.println("提交事务");
		dataSourceTransactionManager.commit(transaction);
	}

	// 回滚事务
	public void rollback() {
		System.out.println("回滚事务...");
		dataSourceTransactionManager.rollback(transactionStatus);
	}

}
package com.learn.aop;

import java.lang.reflect.Method;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;

import com.learn.annotation.ExtTransaction;
import com.learn.transaction.TransactionUtils;

//自定义事务注解具体实现
/**
 * 我自己做了一个封装
 * 也是通过代理设计模式去拦截
 * 为什么代理设计模式也会拦截到注解呢
 * 这个待会我讲一下底层的实现原理
 * 你就知道是怎么做的
 * 这段代码就可以自定注解
 * 然后实现我对事物的一个管理
 * 其实这个大体不是很难
 * 但是我为什么要讲这个呢
 * 我觉得大家要学会一种思想
 * 以后你们一听就说
 * 我们今天要手写一个@Transaction注解出来
 * 举得这个我不会
 * 这个很高大上
 * 那么我告诉你一下
 * 当你学完以后会发现
 * 这个东西没什么难的
 * 就是没什么了不起的
 * 就是这样的
 * 你会了以后眼界就完全不一样了
 * 这个我可以直说的
 * 我这边给大家说一下
 * 你们下去的时候自己去看一下一些源码
 * 也可以下去看一下
 * 我提前说几个任务
 * 最好下去大致去了解一下
 * 我们接下来马上要讲到了
 * 你们自己下去去研究一下原理
 * 你可以去百度上找个文章
 * 去看一下ArrayList是怎么实现的
 * 但是我是这么觉得的
 * 我觉得最难的一个知识是在哪里呢
 * 一个是手写集合框架
 * 一个是手写数据库连接池
 * 这两个是比较难的
 * 可以去网上看一下有没有写数据库连接池
 * 我大体把思路告诉你们
 * 你们去预习一下
 * 否则你们当天会觉得有点抽象
 * 连接池的实现原理
 * 其实数据库连接池的原理
 * 和线程池原理一模一样
 * 里面也是用到了并发
 * 到时候我们讲手写ORM框架的时候
 * 就是实现一个简单版的数据库连接池
 * 做一个注解版本的ORM映射
 * 映射到表里面自动生成一个SQL语句
 * 就是类似于一个hibernate语句
 * 最后分享一下mybatis的api
 * 所以呢我们就不会讲到API了
 * 然后HashMap是我觉得比较难的
 * 要学这个数据结构
 * 像红黑树啊
 * 链表 数组
 * 这些数据结构
 * 所以这两个可能是你们觉得最难的那个
 * 然后后序的时候
 * 尤其是我们分布式微服务讲完的时候
 * 然后就会讲到分布式事务的一个框架
 * 我们当天就写一个框架出来
 * 你写出来的时候你对分布式事务的眼界
 * 绝对是不一样的
 * 就是一个大的亮点
 * 我们到时候会手写RPC
 * 这个手写SpringCloud会简单点
 * 写dubbo会比较难一点
 * 因为SpringCloud是基于http的
 * 底层是通过http封装起来的
 * 所以这个就比较简单了
 * 然后TOMCAT就稍微有点难度了
 * 基于多线程加线程池
 * netty框架加NIO
 * 主要是写一个request和响应出来就OK了
 * 我们大概要讲两个信息
 * 大概讲到月底把整个源码讲完
 * 这可能有点难度
 * 代码量也比较大
 * 大家最好是打一遍
 * 不要听我上课讲
 * 一定要去敲一遍
 * 
 * 
 * 
 * 
 * @author Leon.Sun
 *
 */
@Aspect
@Component
public class AopExtTransaction {
// 一个事务实例子 针对一个事务
@Autowired
private TransactionUtils transactionUtils;

// 使用异常通知进行 回滚事务
@AfterThrowing("execution(* com.learn.service.*.*.*(..))")
public void afterThrowing() {
	// 获取当前事务进行回滚
	// TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
	transactionUtils.rollback();
}

// 环绕通知 在方法之前和之后处理事情
@Around("execution(* com.learn.service.*.*.*(..))")
public void around(ProceedingJoinPoint pjp) throws Throwable {

	// 1.获取该方法上是否加上注解
	ExtTransaction extTransaction = getMethodExtTransaction(pjp);
	TransactionStatus transactionStatus = begin(extTransaction);
	// 2.调用目标代理对象方法
	pjp.proceed();
	// 3.判断该方法上是否就上注解
	commit(transactionStatus);
}

private TransactionStatus begin(ExtTransaction extTransaction) {
	if (extTransaction == null) {
		return null;
	}
	// 2.如果存在事务注解,开启事务
	return transactionUtils.begin();
}

private void commit(TransactionStatus transactionStatus) {
	if (transactionStatus != null) {
		// 5.如果存在注解,提交事务
		transactionUtils.commit(transactionStatus);
	}

}

// 获取方法上是否存在事务注解
private ExtTransaction getMethodExtTransaction(ProceedingJoinPoint pjp)
		throws NoSuchMethodException, SecurityException {
	String methodName = pjp.getSignature().getName();
	// 获取目标对象
	Class<?> classTarget = pjp.getTarget().getClass();
	// 获取目标对象类型
	Class<?>[] par = ((MethodSignature) pjp.getSignature()).getParameterTypes();
	// 获取目标对象方法
	Method objMethod = classTarget.getMethod(methodName, par);
	ExtTransaction extTransaction = objMethod.getDeclaredAnnotation(ExtTransaction.class);
	return extTransaction;
}

}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值