下载APP
登录
关闭
讲堂
算法训练营
Python 进阶训练营
企业服务
极客商城
客户端下载
兑换中心
渠道合作
推荐作者
当前播放: 11 | 什么是Spring的事务抽象(下)
00:00 / 00:00
标清
  • 标清
1.0x
  • 2.0x
  • 1.5x
  • 1.25x
  • 1.0x
  • 0.5x
网页全屏
全屏
00:00
付费课程,可试看

玩转Spring全家桶

共123讲 · 123课时,1300分钟
24700
免费
01 | Spring课程介绍
免费
02 | 一起认识Spring家族的主要...
免费
03 | 跟着Spring了解技术趋势
免费
04 | 编写你的第一个Spring程序
免费
05 | 如何配置单数据源
免费
06 | 如何配置多数据源
07 | 那些好用的连接池们:Hika...
08 | 那些好用的连接池们:Alib...
09 | 如何通过Spring JDBC访问...
10 | 什么是Spring的事务抽象(...
11 | 什么是Spring的事务抽象(...
免费
12 | 了解Spring的JDBC异常抽象
13 | 课程答疑(上)
14 | 课程答疑(下)
15 | 认识Spring Data JPA
16 | 定义JPA的实体对象
17 | 开始我们的线上咖啡馆实战...
18 | 通过Spring Data JPA操...
19 | Spring Data JPA的Repos...
20 | 通过MyBatis操作数据库
21 | 让MyBatis更好用的那些工...
22 | 让MyBatis更好用的那些工...
23 | SpringBucks实战项目进度...
24 | 通过Docker辅助开发
25 | 在Spring中访问MongoDB
26 | 在Spring中访问Redis
27 | Redis的哨兵与集群模式
28 | 了解Spring的缓存抽象
29 | Redis在Spring中的其他用...
30 | SpringBucks实战项目进度...
31 | Project Reactor介绍(上...
32 | Project Reactor介绍(下...
33 | 通过Reactive的方式访问Re...
34 | 通过Reactive的方式访问Mo...
35 | 通过Reactive的方式访问RD...
36 | 通过AOP打印数据访问层的...
37 | 通过AOP打印数据访问层的...
38 | SpringBucks实战项目进度...
39 | 编写第一个Spring MVC C...
40 | 理解Spring的应用上下文
41 | 理解请求的处理机制
42 | 如何定义处理方法(上)
43 | 如何定义处理方法(下)
44 | Spring MVC中的视图解析...
45 | Spring MVC中的视图解析...
46 | Spring MVC中的常用视图...
47 | Spring MVC中的常用视图...
48 | 静态资源与缓存
49 | Spring MVC中的异常处理...
50 | 了解Spring MVC的切入点
51 | SpringBucks实战项目进度...
52 | 课程答疑
53 | 通过RestTemplate访问Web...
54 | RestTemplate的高阶用法
55 | 简单定制RestTemplate
56 | 通过WebClient访问Web资源
57 | SpringBucks实战项目进度...
58 | 设计好的RESTful Web Se...
59 | 设计好的RESTful Web Se...
60 | 什么是HATEOAS
61 | 使用Spring Data REST实...
62 | 使用Spring Data REST实...
63 | 分布式环境中如何解决Sess...
64 | 使用WebFlux代替Spring M...
65 | 使用WebFlux代替Spring M...
66 | SpringBucks实战项目进度...
67 | 认识Spring Boot的组成部...
68 | 了解自动配置的实现原理
69 | 动手实现自己的自动配置
70 | 如何在低版本Spring中快速...
71 | 了解起步依赖及其实现原理
72 | 定制自己的起步依赖
73 | 深挖Spring Boot的配置加...
74 | 理解配置背后的PropertyS...
75 | 认识Spring Boot的各类Ac...
76 | 动手定制自己的Health In...
77 | 通过Micrometer获取运行数...
78 | 通过Spring Boot Admin...
79 | 如何定制Web容器的运行参...
80 | 如何配置容器支持HTTP/2...
81 | 如何配置容器支持HTTP/2...
82 | 如何编写命令行运行的程序
83 | 了解可执行Jar背后的秘密
84 | 如何将Spring Boot应用打...
85 | SpringBucks实战项目进度...
86 | 简单理解微服务
87 | 如何理解云原生(Cloud N...
88 | 12-Factor App(上)
89 | 12-Factor App(下)
90 | 认识Spring Cloud的组成...
91 | 使用Eureka作为服务注册中...
92 | 使用Spring Cloud Loadb...
93 | 使用Feign访问服务
94 | 深入理解服务发现背后的Di...
95 | 使用Zookeeper作为服务注...
96 | 使用Consul作为服务注册中...
97 | 使用Nacos作为服务注册中...
98 | 如何定制自己的Discovery...
99 | SpringBucks实战项目进度...
100 | 使用Hystrix实现服务熔...
101 | 使用Hystrix实现服务熔...
102 | 如何观察服务熔断
103 | 使用Resilience4j实现服...
104 | 使用Resilience4j实现服...
105 | 使用Resilience4j实现服...
106 | SpringBucks实战项目进度...
107 | 基于Git的配置中心(上)
108 | 基于Git的配置中心(下)
109 | 基于Zookeeper的配置中心
110 | 深入理解Spring Cloud的...
111 | 基于Consul的配置中心
112 | 基于Nacos的配置中心
113 | SpringBucks实战项目进度...
114 | 认识Spring Cloud Stre...
115 | 通过Spring Cloud Stre...
116 | 通过Spring Cloud Stre...
117 | SpringBucks实战项目进度...
118 | 通过Dapper理解链路治理
119 | 使用Spring Cloud Sleu...
120 | 如何追踪消息链路
121 | 除了链路还要治理什么
122 | SpringBucks实战项目进度...
123 | 结束语
本节摘要

PDF 课件和源代码下载地址:

https://github.com/geektime-geekbang/geektime-spring-family

猜你喜欢

unpreviewunpreview

展开

精选留言(60)

  • 2019-02-17
    第一步:注入实例
      @Autowired
        private FooService fooService;
    第二步:添加实现
       //把自己的实例注入进来,比较方便理解
        @Override
        public void invokeInsertThenRollbackBySelfService() throws RollbackException {
            fooService.insertThenRollback();
        }
        //获取当前代理,这样写避免了自己调用自己的实例
        @Override
        public void invokeInsertThenRollbackByAopContext() throws RollbackException {
            ((FooService) (AopContext.currentProxy())).insertThenRollback();
        }
        //再加一层事务
        @Transactional(rollbackFor = RollbackException.class)
        @Override
        public void invokeInsertThenRollbackAddTransactional() throws RollbackException {
            insertThenRollback();
        }
    第三步:添加测试方法
    可以先注释CommandLineRunner里面的内容
    @Slf4j
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class DeclarativeTransactionDemoApplicationTests {
        @Autowired
        private FooService fooService;
        @Autowired
        private JdbcTemplate jdbcTemplate;
        @Test
        public void invokeInsertThenRollback() {
            try {
                fooService.invokeInsertThenRollback();
            } catch (Exception e) {
                log.info("BBB {}",
                        jdbcTemplate
                                .queryForObject("SELECT COUNT(*) FROM FOO WHERE BAR='BBB'", Long.class));
            }
        }
        @Test
        public void invokeInsertThenRollbackBySelfService() {
            try {
                fooService.invokeInsertThenRollbackBySelfService();
            } catch (Exception e) {
                log.info("BBB {}",
                        jdbcTemplate
                                .queryForObject("SELECT COUNT(*) FROM FOO WHERE BAR='BBB'", Long.class));
            }
        }
        @Test
        public void invokeInsertThenRollbackByAopContext() {
            try {
                fooService.invokeInsertThenRollbackByAopContext();
            } catch (Exception e) {
                log.info("BBB {}",
                        jdbcTemplate
                                .queryForObject("SELECT COUNT(*) FROM FOO WHERE BAR='BBB'", Long.class));
            }
        }
        @Test
        public void invokeInsertThenRollbackAddTransactional() {
            try {
                fooService.invokeInsertThenRollbackAddTransactional();
            } catch (Exception e) {
                log.info("BBB {}",
                        jdbcTemplate
                                .queryForObject("SELECT COUNT(*) FROM FOO WHERE BAR='BBB'", Long.class));
            }
        }

    }
    展开

    作者回复: 干得漂亮

    66
  • T
    2019-02-13
    ...
    @Autowired
    private FooService fooService;
    ..
    @Override
    public void invokeInsertThenRollback() throws RollbackException{
      fooService.insertThenRollback();
    }
    ...
    展开
    40
  • 2019-02-11
    在当前类的方法中通过AopContext.currentProxy()获取当前类的代理对象,再调用的代理对象的方法(其实是增强后的方法),事务就会生效了。

    作者回复: 是的,你提到了代理,可以把自己的实例注入进来,内部方法调用改为直接调用注入的实例。因为Spring其实是为你创建了一个代理,那我们调用代理就好了。其效果是一样的。

    17
  • 2019-02-11
    思考题答案:((FooService) (AopContext.currentProxy())).insertThenRollback();测过了是对的。
    但我觉得最好的方法是避免这种内部调用

    作者回复: 这是一种方法,还有种更简单的做法是把自己的实例注入进来,内部方法调用改为直接调用注入的实例。因为Spring其实是为你创建了一个代理,那我们调用代理就好了。

    1
    12
  • 2019-02-27
    以前就踩过这个坑。默认情况下 Spring Aop 同级调用会失效,原因是同级无法创建代理对象.
    9
  • 2019-02-13
    方法添加事务注解,应该就可以了

    作者回复: 这……也是个办法,但不是我这个问题的本意哈

    6
  • 2019-02-13
    一个类自身调用自身的方法,例如A()调用B(),此时B方法的事务不起作用,由于事务增强处理是交给aop生成的代理类完成,A()方法未做事务处理,那么调用代理类的A()方法同样不具备事务。
     需要把A()移到不同于B()的类中,即可达到预期效果

    作者回复: 事务的确是AOP代理来实现的,不过你这里的A和B把我说晕了……把类的内部调用改成不同类之间的调用,其本质其实也是调用代理类的方法,所以效果是一样的。

    6
  • 比较想问的是学完框架后,是先学设计模式还是先学JVM原理,并发与线程安全,然后中间件和架构设计,数据库设计,Linux学习,跨语言学习顺序,这些都是按照什么样的顺序学习的,还有源码阅读顺序

    作者回复: 你说的这些如果是做Java后端的话,迟早都是要接触到的,个人觉得无所谓先后,建议先广泛地涉猎这些知识,并不一定要很精通,但要知道了解,一旦遇到了问题,要能在第一时间想到在哪里能找到相关的材料,能快速拎起来。

    5
  • 2019-03-06
    注入自己,通过类名.调用就可以了。在这里踩过坑,所以记忆犹新。不实现接口的cglib代理也是一样
    4
  • 2019-02-15
    @Component
    public class FooServiceImpl implements FooService {
        @Autowired
        private JdbcTemplate jdbcTemplate;

        @Autowired
        private FooServiceImpl self;

        @Override
        @Transactional(rollbackFor = Exception.class)
        public void insertRecord() {
            jdbcTemplate.execute("INSERT INTO FOO (BAR) VALUES ('AAA')");
        }

        @Override
        @Transactional(rollbackFor = RollbackException.class)
        public void insertThenRollback() throws RollbackException {
            jdbcTemplate.execute("INSERT INTO FOO (BAR) VALUES ('BBB')");
            throw new RollbackException();
        }

        @Override
        public void invokeInsertThenRollback() throws RollbackException {
            self.insertThenRollback();
        }
    }
    展开
    4
  • 2019-02-13
    讲的内容偏重于应用,是否可以深入的说下,比如,事物执行的原理,详细的说下,这样能加深理解,也能明白各个属性具体怎么工作的, 在执行过程中,怎么起作用。只讲偏应用,过去之后,就忘记了。

    作者回复: 你好,这个部分的确以应用为主一些,后续的章节有些地方会做展开,考虑到大部分同学的情况,不会在课程中就每个点都去展开,还请理解。相信你提了这个问题,那应该也能从我在课程中说道的Spring的事务其实是通过AOP实现的这句中理解事务的原理,对吧:-)

    4
  • 2019-03-07
    如果把FooServiceImpl类中的方法全部去掉@Transactional注解,然后在类上加上@Transactional(rollbackFor = RollbackException.class),也能产生同样的结果,这样可以吗?

    作者回复: 在类上加@Transacational注解,则类里的public方法都会带上事务。而且属性都是用同一个。

    3
  • 2019-02-14
    ApplicationContext.getBean("fooService" ).insert...

    作者回复: 只要能取得代理对象,执行代理的方法就行。

    2
  • 2019-07-19
    老师,我想问下为什么把@EnableTransactionManagement(mode= AdviceMode.PROXY)这一行注释掉,
    效果也是一样的,也用了事务。只用@Transactional就可以开启事务了吗?那@EnableTransactionManagement的具体作用又是什么呢?谢谢老师,如果有大佬看到了,也希望回答下我的问题,谢谢了~

    作者回复: 你没写并不代表没有,Spring Boot给我们做了自动配置

    1
  • 2019-06-18
    老师 请问一下 我的方法中有操作不同数据库的操作 比如操作mysql redis ,在异常后无法回滚。这种情况我该怎么办呢

    作者回复: Redis不算RDBMS,算NoSQL,MySQL和Redis本来就没有自动的事务关联,你只能手写,在MySQL回滚时自己清理Redis。哪怕是两个MySQL,也没有很好的分布式事务实现,JTA这种性能不是很理想,基本都是要靠自己实现,关于分布式事务可以了解下BASE和TCC的概念。

    1
  • t
    2019-06-05
    插个眼,这个肯定以后会碰到这个坑
    1
  • 2019-02-16
    老师能不能把每次提的问题,在下一小节中做一个解答呢?比如说第三个方法的调用,有人说通过获取代理对象,然后调用增强后的方法。而您有更好的解决办法,希望补充一个代码示例。

    作者回复: 在答疑的课程中会简单说明的,这里大家解决的思路都大同小异。

    1
  • 2019-02-13
    将普通方法调用的方式改为使用代理的方式进行访问
    1
  • 2019-02-13
    直接在invokeInsertThenRollback() 加事务注解不行吗?

    作者回复: 额,这里就是想演示一下不带注解的方法内部调用带注解的方法的情况……

    1
  • 2019-11-03
    老师。我并没有改动@EnableTransactionManagement的proxyTargetClass属性。
    只是写了一个实现类,没有实现接口。但是,也能该实现类中的方法也能实现事务的效果。这是为什么呢?
    代理类应该是通过接口进行增强的吧,没有接口为啥也可以呢

    作者回复: SpringBoot有很多自动配置的,已经把proxyTargetClass给你设置为true了

    2