使用AOP功能和ThreadLocal类实现自定义事务管理

使用AOP功能和ThreadLocal类实现自定义事务管理

首先,需要理解ThreadLocal类的作用。ThreadLocal是为了在同一个线程中共享数据,具体原理可以参考源代码,如下:

public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value);}

设置值实际上就是通过map存放的,与map不同的是固定将当前线程作为key值。

public T get() {

Thread t = Thread.currentThread();

ThreadLocalMap map = getMap(t);

if (map != null) {

ThreadLocalMap.Entry e = map.getEntry(this);

if (e != null) {

@SuppressWarnings("unchecked")

T result = (T)e.value;

return result;

}

}

return setInitialValue();

}

获取值时通过当前线程去获取值,所以如果在同一个线程中,前面存进去的值,后面是可以取出来用的,以达到线程共享数据的目的。

接下来的例子中,主要是把一个线程中的连接共享,以达到一个线程共享一个连接,因为只有这样,才能够做到事务操作,因为同一个事务必须要求在同一个连接中,才能保证数据安全。具体代码如下:

@Component

public class DBManager {

/**

* 使用map的方式存储数据,key使用当前线程,所以能够保证一个线程共享数据,此处用来在一个线程中共享一个数据库连接

*/

private ThreadLocal<Connection> threadLocal = new ThreadLocal<>();

@Value("${jdbc.url}") // 使用读取properties配置文件中的数据加载url

private String url;

@Value("${jdbc.driver}")

private String driver;

@Value("${jdbc.user}")

private String username;

@Value("${jdbc.password}")

private String password;

/**

* 创建一个新的连接

* @return

* @throws Exception

*/

private Connection createConnection() throws Exception {

Class.forName(driver);

return DriverManager.getConnection(url, username, password);

}

public Connection getConnection() throws Exception {

// 在ThreadLocal集合中获得以当前线程为key的连接对象

Connection connection = threadLocal.get();

// 如果获取到了连接则返回连接

if (connection != null && !connection.isClosed()){

return connection;

}else {

// 如果连接不存在或者已经关闭则创建新的连接并把连接存到ThreadLocal集合中

connection = createConnection();

threadLocal.set(connection);

return connection;

}

}

public void closeConnection(){

// 在ThreadLocal集合中获得以当前线程为key的连接对象

Connection connection = threadLocal.get();

try {

// 如果获取到了连接则关闭连接,并且将集合中设置为null

if (connection != null && !connection.isClosed()){

connection.close();

threadLocal.set(null);

}

}catch (Exception e){

e.printStackTrace();

}

}

}

在service层中,由于所有的方法都需要处理业务之外的内容,比如连接开启和关闭,事务的提交回滚等,这些应该属于AOP中切面的内容,可以提取出来解决,切面代码如下:(通过设置service层的around通知完成)

@Component

public class MyTransaction {

@Resource

private DBManager dbManager;

// 使用aop的around的方式处理事务

public Object doTransacition(ProceedingJoinPoint pjp){

Connection connection = null;

Object result = null;

// 得到实际调用的service中方法的名称

String methodName = pjp.getSignature().getName();

try {

connection = dbManager.getConnection();

// 判断方法的名称是否需要事务操作(增、删、改需要事务操作)

if (methodName.startsWith("update") || methodName.startsWith("save") ||

methodName.startsWith("delete")){

// 设置事务关闭自动提交

connection.setAutoCommit(false);

// 实际业务方法执行

result = pjp.proceed();

// 提交事务

connection.commit();

}else {

result = pjp.proceed();

}

}catch (Throwable e){

e.printStackTrace();

if (connection != null){

// 判断方法的名称是否需要事务的回滚操作操作(增、删、改需要事务操作)

if (methodName.startsWith("update") || methodName.startsWith("save") ||

methodName.startsWith("delete")){

try {

connection.rollback();

} catch (SQLException e1) {

e1.printStackTrace();

}

}

}

}finally {

// 关闭连接

dbManager.closeConnection();

}

return result;

}

}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,324评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,356评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,328评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,147评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,160评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,115评论 1 296
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,025评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,867评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,307评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,528评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,688评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,409评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,001评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,657评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,811评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,685评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,573评论 2 353

推荐阅读更多精彩内容