@Transaction原理解讀之如何實現一個精簡版的@MyTransation

一、定義一個註解

@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技術人的選擇!

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章