一、定義一個註解
@Target({ElementType.METHOD})表示aop攔截的是方法上的註解
package com.biubiu.transaction;
import java.lang.annotation.*;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyTransaction {
}
二、實現事物管理器
與之前一篇博客一樣要保證的是 ,這個很重要
不同的線程使用的是不同的連接
同一個線程使用同一個連接
package com.biubiu.transaction;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
/**
* @author yule.zhang
* @date 2019/9/29 23:01
* @email [email protected]
* @description a
*/
@Component
public class MyTransactionManager {
@Resource
private DataSource dataSource;
//保證不同的線程使用的是不同的連接,同一個線程使用同一個連接
ThreadLocal<Connection> threadLocal = new ThreadLocal<>();
Connection connection = null;
public Connection getConnection() throws SQLException {
connection = threadLocal.get();
if(connection != null) {
return connection;
} else {
connection = dataSource.getConnection();
threadLocal.set(connection);
}
return connection;
}
}
三、實現aop
package com.biubiu.transaction;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
/**
* @author yule.zhang
* @date 2019/9/29 23:41
* @email [email protected]
* @description 切面
*/
@Component
@Aspect
public class EventAspect {
@Resource
private MyTransactionManager myTransactionManager;
@Around("@annotation(com.biubiu.transaction.MyTransaction)")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
Connection connection = null;
Statement stmt = null;
Object val = null;
try{
connection = myTransactionManager.getConnection();
connection.setAutoCommit(false);
//執行目標方法
val = joinPoint.proceed();
//提交
connection.commit();
}catch(Exception e) {
try {
connection.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
} finally {
if(stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return val;
}
}
四、補充說明
只是實現了一個精簡版的功能,官方框架中尚且還有許多功能這裏沒有選擇實現,如 選擇事物隔級別,選擇異常處理級別,因爲默認是RunTimeException級別纔會拋出異常,還有當有新的請求時是否創建新的事物來執行。
五、最後再推薦一個編程方向的公衆號,您的專注是我創作的最大動力。
號主爲一線大廠架構師,博客訪問量突破一千萬。主要分享Java、golang架構,源碼,分佈式,高併發等技術,用大廠程序員的視角來探討技術進階、面試指南、職業規劃等。15W技術人的選擇!