首页 > 其他分享 >【Spring事务底层实现原理】

【Spring事务底层实现原理】

时间:2023-09-16 10:35:33浏览次数:35  
标签:事务 拦截器 Spring void 代理 bean public 底层

@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);
}

实现这个接口的目标类:

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;
    }
}

定义一个事务拦截器类:

/**
 * 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;
    }
}

定义一个上下文容器类:

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; // 返回原始对象
    }
}

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

/**
 * 代理工厂类,用于创建代理对象
 */
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(); // 创建代理对象并返回
    }
}

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

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);
    }
}

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

标签:事务,拦截器,Spring,void,代理,bean,public,底层
From: https://blog.51cto.com/liaozhiweiblog/7491426

相关文章

  • springmvc中设置文件的上传与下载,首先需要导入依赖,之后需要在springmvc.xml中配置问价
    2023-09-16导入依赖<dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.4</version></dependency>设置文件上传解析器springmvc.xml<?xml......
  • Springboot+WebSocket 实现IM及时通讯
    1、Springboot集成Websocket集成分为三步:添加依赖、增加配置类和消息核心类、前端集成。1.1、添加依赖<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId><version>2.1.13.RELEASE</version......
  • 详解Spring Boot如何实现每日给女朋友微信推送早安问候语和天气预报浪漫教程
    每天早上可以给指定的微信用户推送消息,经过公众号可以使用第三方接口丰富推送的消息内容百度天气api:添加天气信息推送天行数据api:添加美句、彩虹屁等语句推送通过后台计算纪念日推送......效果图技术栈点springboot实现后台微信测试账号的申请微信模版推送的配置对接百度天气api对......
  • sqlserver存储过程报错:当前事务无法提交,而且无法支持写入日志文件的操作。请回滚该事
    ​ ​编辑 现象:系统出现异常,手动执行过程提示如上。  问题排查:1.直接执行的过程事务挂起(排除)2.重启数据库实例(重启后无效)3.过程中套用过程,套用的过程中使用事务,因为插入的表结构字段超出最大长度(修改表结构问题恢复) 结论:事务执行失败,嵌套层级太深。  ​......
  • MySQL——事务
    是什么必须被原子地执行的一个或多个数据库操作的集合,事务用于保证数据的一致性。如:转账就要用事务来处理,用以保证数据的一致性。当执行事务操作时,mysql会在表上加锁,防止其他操作对表进行修改。事务的特性ACID原子性Atomicity一致性Consistency隔离性Isolation持久性Durabi......
  • Java中HashMap的底层实现原理
     ......
  • spring依赖注入单例模式下(默认都是单例),类变量(实例变量)线程安全问题
    java变量是程序中最基本的存储单元,其要素包括变量名,变量类型和作用域。Java的变量类型有:   成员变量类中的变量(独立于方法之外的变量)   局部变量类的方法中的变量。而java类的成员变量又有俩种:   静态变量(类变量):独立于方法之外的变量,用static修饰。   实例变......
  • 在springboot中处理UDP流
    配置: <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-integration</artifactId></dependency><dependency><groupId>org.springframework.integration</gr......
  • springboot+vue导出本地可执行文件
    1、前端页面增加下载链接<ahref="http://localhost:80/system/download"download="xxx.exe">下载地址</a>2、后端读取文件下载//下载文件@GetMapping("/system/download")publicvoiddownload(HttpServletResponseresponse){S......
  • mac版本Spring5.0源码环境搭建
    下载spring5.0版本代码链接是:https://github.com/spring-projects/spring-framework.git装gradle,使用的版本是8.3版本链接是:https://gradle.org/next-steps/?version=8.3&format=bin有错误提示:/Users/wangyu/work/code/spring-framework/buildSrc/src/main/java/org/springfra......