• 【Spring事务底层实现原理】


    @Transactional注解

    Spring使用了TransactionInterceptor拦截器,该拦截器主要负责事务的管理,包括开启、提交、回滚等操作。当在方法上添加@Transactional注解时,Spring会在AOP框架中对该方法进行拦截,TransactionInterceptor会在该方法执行前后,对事务进行切面处理,Spring会基于该类生成一个代理对象,把这个代理对象作为bean。当调用这个代理对象的方法时,如果有事务处理,则会先关闭事务的自动功能,然后执行方法的具体业务逻辑,如果业务逻辑没有异常,那么代理逻辑就会直接提交,如果出现任何异常,那么直接进行回滚操作。

    事务管理器

    Spring还提供了多种事务管理器,包括JDBC事务管理器、Hibernate事务管理器、JTA事务管理器等等,可以满足不同数据访问层的需求。事务通知是Spring事务机制中的一个重要组成部分,主要用于判断哪些方法需要被事务管理,以及如何管理事务。

    Spring事务底层实现原理

    应用启动时会创建一个代理类,把事务逻辑织入到代理类中,然后用代理类替代目标类,并放入上下文容器中。当实际调用目标类的事务方法时,被代理类拦截,先执行拦截器中的事务逻辑,再执行目标类的业务逻辑,最后处理异常回滚和提交。这样就能实现简单、方便、可控的事务管理。

    示例代码

    这里给出一个简单的示例代码:

    定义一个接口,包含需要进行事务管理的方法:

    public interface UserService {
        void addUser(User user);
        void deleteUser(String id);
        void updateUser(User user);
        User getUser(String id);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    实现这个接口的目标类:

    public class UserServiceImpl implements UserService {
        @Override
        public void addUser(User user) {
            //添加用户的业务逻辑
        }
        @Override
        public void deleteUser(String id) {
            //删除用户的业务逻辑
        }
        @Override
        public void updateUser(User user) {
            //更新用户的业务逻辑
        }
        @Override
        public User getUser(String id) {
            //查询用户的业务逻辑
            return null;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    定义一个事务拦截器类:

    /**
     * TransactionInterceptor 是一个实现了 MethodInterceptor 接口的拦截器类
     */
    public class TransactionInterceptor implements MethodInterceptor {
        /**
         * TransactionManager 对象,用于管理事务
         */
        private TransactionManager txManager;
        /**
         * 用于注入 TransactionManager 对象
         * @param txManager TransactionManager 对象
         */
        public void setTxManager(TransactionManager txManager) {
            this.txManager = txManager;
        }
        /**
         * 实现 MethodInterceptor 接口的 invoke 方法,用于拦截指定方法
         * @param invocation MethodInvocation 对象,用于获取被拦截的方法及其参数
         * @return 执行方法的返回结果
         * @throws Throwable 抛出异常
         */
        @Override
        public Object invoke(MethodInvocation invocation) throws Throwable {
            Object result;
            try {
                // 开启事务
                txManager.start();
                // 执行被拦截的方法,并获取方法执行的返回结果
                result = invocation.proceed();  
                // 提交事务
                txManager.commit();
            } catch (Exception e) {
                // 回滚事务
                txManager.rollback();
                throw e;
            }
            return result;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    定义一个上下文容器类:

    public class ApplicationContext {
        private Map<String, Object> beanMap = new HashMap<>(); // 用于存放bean的map
        // 注册bean
        public void registerBean(String name, Object bean) {
            beanMap.put(name, bean); // 将bean存放到map中
        }
        // 获取bean
        public Object getBean(String name) {
            Object bean = beanMap.get(name); // 从map中获取bean
            if (bean instanceof Advised) { // 如果bean是Advised类型,说明使用了AOP
                return ((Advised)bean).getTargetSource().getTarget(); // 返回目标对象
            }
            return bean; // 返回原始对象
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在应用启动时,创建一个代理工厂类,使用上述事务拦截器对目标类进行代理:

    /**
     * 代理工厂类,用于创建代理对象
     */
    public class ProxyFactory {
        /**
         * 创建代理对象
         * @param target 目标对象,需要被代理的对象
         * @param interceptor 事务拦截器,代理对象需要加入该拦截器
         * @return 返回代理对象
         */
        public static Object createProxy(Object target, TransactionInterceptor interceptor) {
            DefaultAopProxyFactory proxyFactory = new DefaultAopProxyFactory();
            AdvisedSupport advisedSupport = new AdvisedSupport();
            advisedSupport.setTarget(target); // 设置目标对象
            advisedSupport.addAdvice(interceptor); // 添加事务拦截器
            return proxyFactory.createAopProxy(advisedSupport).getProxy(); // 创建代理对象并返回
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    然后在应用启动时,创建容器并注册代理类:

    public class Main {
        public static void main(String[] args) {
            ApplicationContext context = new ApplicationContext();
            UserService target = new UserServiceImpl(); //创建目标类
            TransactionInterceptor interceptor = new TransactionInterceptor();
            interceptor.setTxManager(new TransactionManager()); //设置事务管理器
            UserService proxy = (UserService) ProxyFactory.createProxy(target, interceptor); //创建代理类
            context.registerBean("userService", proxy); //注册代理类到上下文容器中
            //使用代理类进行业务操作
            User user = new User();
            context.getBean("userService").addUser(user);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    这样,当执行代理类的方法时,就会先执行事务拦截器中的事务逻辑,再执行目标类的业务逻辑。如果出现异常,会进行回滚。这样就实现了简单、方便、可控的事务管理。

  • 相关阅读:
    阿里云3M固定带宽服务器速度快吗?是否够用?
    代码随想录算法训练营第23期day24|回溯算法理论基础、77. 组合
    c++-继承详解
    [创业之路-85]:IT创业成功老板的品质、创业失败老板的特征、成功领导者的品质、失败管理者的特征
    标准差有两种常见的估计方法:有偏估计和无偏估计
    babili-webpack-plugin编译后的代码v+‘‘===1,会被压缩成字符串v1
    关于Keil编译程序出现“File has been changed outside the editor,reload?”的解决方法
    《opencv学习笔记》-- 寻找已知物体
    Svelte 实现 keypress 快捷键功能
    xss-labs/level15
  • 原文地址:https://blog.csdn.net/java_wxid/article/details/132889539