我试图通过这篇文章,教会你一种阅读源码的方式。

Unity URP源码阅读指南:从原理到实践,掌握渲染管线核心技术 在计算机图形学中,渲染管线是决定三维场景如何转换为二维图像的核心技术框架。其原理涉及顶点处理、光栅化、像素着色等多个阶段,通过可编程着色器实现复杂视觉效果。对于Unity开发者而言,理解通用渲染管线(URP)的底层机制,不仅能解决自定义渲染效果、性能优化等工程实践难题,更是从工具使用者进阶为技术专家的关键路径。通过源码阅读,开发者可以深入掌握CameraRenderer的工作流程、ScriptableRenderPass的扩展机制以及ShaderLibrary的核心算法,从而在游戏开发、虚拟现实、影视特效等 阅读详情

是的,正如标题描述的这样,我试图通过这篇文章,教会你如何阅读源码。

事情大概是这样的,前段时间,我收到了一个读者发来的类似于这样的示例代码:

他说他知道这三个案例的回滚情况是这样的:

  • insertTestNoRollbackFor:不会回滚
  • insertTestRollback:会回滚
  • insertTest:会回滚

他说在没有执行代码之前,他也知道前两个为什么一个不会回滚,一个会回滚。因为抛出的异常和 @Transactional 里面的注解呼应上了。

但是第三个到底会不会回滚,没有执行之前,他不知道为什么会回滚。执行之后,回滚了,他也不知道为什么回滚了。

我告诉他:源码之下无秘密。

让他去看看这部分源码,理解它的原理,不然这个地方抛出一个其他的异常,又不知道会不会回滚了。

但是他说他完全不会看源码,找不到下手的角度。

所以,就这个问题,我打算写这样的一篇文章,试图教会你一种阅读源码的方式。让你找到一个好的切入点,或者说突破口。

但是需要事先说明的是,阅读源码的方式非常的多,这篇文章只是站在我个人的角度介绍阅读源码的众多方式中的一种,沧海一粟,就像是一片树林里面的一棵树的树干上的一叶叶片的叶脉中的一个小分叉而已。

对于啃源码这件事儿,没有一个所谓的“一招吃遍天下”的秘诀,如果你非要让我给出一个秘诀的话,那么就只有一句话:

啃源码的过程,一定是非常枯燥的,特别是啃自己接触不多的框架源码的时候,千头万绪,也得下手去捋,所以一定要耐得住寂寞才行。

然后,如果你非得让我再补充一句的话,那么就是:

调试源码,一定要亲!自!动!手!只是去看相关的文章,而没有自己一步步的去调试源码,那你相当于看了个寂寞。

亲自动手的第一步就是搞个 Demo 出来。用“黑话”来说,这个 Demo 就是你的抓手,有了抓手你才能打出一套理论结合实际的组合拳。抓手多了,就能沉淀出可复用的方法论,最终为自己赋能。

搭建 Demo

所以,第一步肯定是先把 Demo 给搭建起来,项目结构非常的简单,标准的三层结构:

主要是一个 Controller,一个 Service,然后搞个本地数据库给接上,就完全够够的了:

Student 对象是从表里面映射过来的,随便弄了两个字段,主要是演示用:

就这么一点代码,给你十分钟,你是不是就能搭建好了?中间甚至还能摸几分钟鱼。

要是只有这么一点东西的、极其简单的 Demo 你都不想自己亲自动手搭一下,然后自己去调试的话,仅仅是通过阅读文章来肉眼调试,那么我只能说:

在正式开始调试代码之前,我们还得明确一下调试的目的:想要知道 Spring 的 @Transactional 注解对于异常是否应该回滚的判断逻辑具体是怎么样的。

带着问题去调试源码,是最容易有收获的,而且你的问题越具体,收获越快。你的问题越笼统,就越容易在源码里面迷失。

方法论之关注调用栈

自己 Debug 的过程就是不断的打断点的过程。

我再说一次:自己 Debug 的过程就是不断的打断点的过程。

打断点大家都会打,断点打在哪些地方,这个玩意就很讲究了。

在我们的这个 Demo 下,第一个断点的位置非常好判断,就打在事务方法的入口处:

一般来说,大家调试业务代码的时候,都是顺着断点往下调试。但是当你去阅读框架代码的时候,你得往回看。

什么是“往回看”呢?

当你的程序在断点处停下的时候,你会发现 IDEA 里面有这样的一个部分:

这个调用栈是你在调试的过程中,一个非常非常非常重要的部分。

它表示的是以当前断点位置为终点的程序调用链路。

为了让你彻底的明白这句话,我给你看一张图:

我在 test6 方法中打上断点,调用栈里面就是以 test6 方法为终点到 main 方法为起点的程序调用链接。

当你去点击这个调用栈的时候,你会发现程序也会跟着动:

“跟着动”的这个动作,你可以理解为你站着断点处“往回看”的过程。

当你理解了调用栈是干啥的了之后,我们再具体看看在当前的 Demo 下,这个调用栈里面都有写啥:

标号为 ① 的地方,是 TestController 方法,也就是程序的入口。

标号为 ② 的地方,从包名称可以看出是 String AOP 相关的方法。

标号为 ③ 的地方,就可以看到是事务相关的逻辑了。

标号为 ④ 的地方,是当前断点处。

好,到这里,我想让你简单的回顾一下你来调试代码的目的是什么?

是不是想要知道 Spring 的 @Transactional 注解对于异常是否应该回滚的判断逻辑具体是怎么样的。

那么,我们是不是应该主要把关注的重点放在标号为 ③ 的地方?

也就是对应到这一行:

这个地方我一定要特别的强调一下:要保持目标清晰,很多人在源码里面迷失的原因就是不知不觉间被源码牵着走远了。

比如,有人看到标号为 ② 的部分,也就是 AOP 的部分,一想着这玩意我眼熟啊,书上写过 Spring 的事务是基于 AOP 实现的,我去看看这部分代码吧。

当你走到 AOP 里面去的时候,路就开始有点走偏了。你明白我意思吧?

即使在这个过程中,你翻阅了这部分的源码,确实了解到了更多的关于 AOP 和事务之间的关系,但是这个部分并不解决你“关于回滚的判断”这个问题。

然而更多更真实的情况可能是这样的,当你点到 AOP 这部分的时候,你一看这个类名称是 CglibAopProxy:

你一细嗦,Cglib 你也熟悉啊,它和 JDK 动态代理是一对好兄弟,都是老八股了。

然后你可能又会点击到 AopProxy 这个接口,找到 JdkDynamicAopProxy:

接着你恍然大悟:哦,我在什么都没有配置的情况下,当前版本的 SpringBoot 默认使用的是 Cglib 作为动态代理的实现啊。

诶,我怎么记得我背的八股文默认是使用 JDK 呢?

网上查一下,查一下。

哦,原来是这么一回事儿啊:

  • SpringBoot 1.x,默认使用的是 JDK 动态代理。
  • SpringBoot 2.x 开始,为了解决使用 JDK 动态代理可能导致的类型转化异常而默认使用 CGLIB。
  • 在 SpringBoot 2.x 中,如果需要默认使用 JDK 动态代理可以通过配置项spring.aop.proxy-target-class=false来进行修改,proxyTargetClass配置已无效。

刚刚提到了一个 spring.aop.proxy-target-class 配置,这是个啥,咋配置啊?

查一下,查一下...

喂,醒一醒啊,朋友,走远了啊。还记得你调试源码的目的吗?

如果你对于 AOP 这个部分感兴趣,可以先进行简单的记录,但是不要去深入的追踪。

不要觉得自己只是随便看看,不要紧。反正正是因为这些“随便看看”导致你在源码里面忙了半天感觉这波学到了,但是停下来一想:我 TM 刚刚看了些啥来着?我的问题怎么还没解决?

我为什么要把这部分非常详尽,甚至于接近啰嗦的写一遍,就是因为这个就是初看源码的朋友最容易犯的错误。

特别强调一下:抓住主要矛盾,解决主要问题。

好,回到我们通过调用栈找到的这个和事务相关的方法中:

org.springframework.transaction.interceptor.TransactionInterceptor#invoke

这个方法,就是我们要打第二个断点,或者说这才是真正的第一个断点的地方。

然后,重启项目,重新发起请求,从这个地方就可以进行正向的调试,也就是从框架代码一步步的往业务代码执行。

比如这个方法接着往下 Debug,就来到了这个地方:

org.springframework.transaction.interceptor.TransactionAspectSupport#invokeWithinTransaction

找到了这个地方,你就算是无限的接近于问题的真相了。

这个部分我肯定会讲的,但是在这里先按下不表,毕竟这并不是本文最重要的东西。

本文最重要的是,我再次重申一遍:我试图想要教会你一种阅读源码的方式,让你找到一个好的切入点,或者说突破口。

由于这个案例比较简单,所以很容易找到真正的第一个利于调试的断点。

如果遇到一些复杂的场景、响应式的编程、异步的调用等等,可能会循环往复的执行上面的动作。

分析调用栈,打断点,重启。

再分析调用栈,再打断点,再重启。

方法论之死盯日志

其实我发现很少有人会去注意框架打印的日志,就像是很少有人会去仔细阅读源码上的 Javadoc 一样。

但是其实通过观察日志输出,也是一个很好的寻找阅读源码突破口的方式。

我们要做的,就是保证 Demo 尽量的单纯,不要有太多的和本次排查无关的代码和依赖引入。

然后把日志级别修改为 debug:

logging.level.root=debug

接着,就是发起一次调用,然后耐着性子去看日志。

还是我们的这个 Demo,发起一次调用之后,控制台输出了很多的日志,我给你搞个缩略图看看:

我们已知的是这里面大概率是有线索的,有没有什么方法尽量快的找出来呢?

有,但是通用性不强。所以如果经验不够丰富的话,那么最好的方法就是一行行的去找。

前面我也说过了:啃源码的过程,一定是非常枯燥的。

所以你一定会找到这样的日志输出:

Acquired Connection [HikariProxyConnection@982684417 wrapping com.mysql.cj.jdbc.ConnectionImpl@751a148c] for JDBC transaction
Switching JDBC Connection [HikariProxyConnection@982684417 wrapping com.mysql.cj.jdbc.ConnectionImpl@751a148c] to manual commit
...
==>  Preparing: insert into student ( name, home ) values ( ?, ? ) 
HikariPool-1 - Pool stats (total=1, active=1, idle=0, waiting=0)
==> Parameters: why(String), 草市街199号-insertTestNoRollbackFor(String)
<==    Updates: 1
...
Committing JDBC transaction on Connection [HikariProxyConnection@982684417 wrapping com.mysql.cj.jdbc.ConnectionImpl@751a148c]
Releasing JDBC Connection [HikariProxyConnection@982684417 wrapping com.mysql.cj.jdbc.ConnectionImpl@751a148c] after transaction

这几行日志,不就是正对应着 Spring 事务的开启和提交吗?

有了日志,我们完全可以基于日志去找对应的日志输出的地方,比如我们现在要找这一行日志输出对应的代码:

o.s.j.d.DataSourceTransactionManager : Acquired Connection [HikariProxyConnection@982684417 wrapping com.mysql.cj.jdbc.ConnectionImpl@751a148c] for JDBC transaction

首先,我们可以根据日志知道对应输出的类是 DataSourceTransactionManager 这个类。

然后找到这个类,按照关键词搜索:

不就找到这一行代码了吗?

或者我们直接秉承大力出奇迹的真理,来一个暴力的全局搜索,也是能搜到这一行代码的:

再或者修改一下日志输出格式,把行号也搞出来嘛。

当我们把日志格式修改为这样之后:

logging.pattern.console=%d{dd-MM-yyyy HH:mm:ss.SSS} %magenta([%thread]) %highlight(%-5level) %logger.%M:%L - %msg%n

控制台的日志就变成了这样:

org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin:263 - Acquired Connection [HikariProxyConnection@1569067488 wrapping com.mysql.cj.jdbc.ConnectionImpl@19a49539] for JDBC transaction

很直观的就看出来了,这行日志是 DataSourceTransactionManager 类的 doBegin 方法,在 263 行输出的。

然后你找过去,发现没有任何毛病,这就是案发现场:

我前面给你说这么多,就是为了让你找到这一行日志输出的地方。

现在,找到了,然后呢?

然后肯定就是在这里打断点,然后重启程序,重新发起调用了啊。

这样,你又能得到一个调用栈:

然后,你会从调用栈中看到一个我们熟悉的东西:

朋友,这不就和前面写的“方法论之关注调用栈”呼应起来了吗?

这不就是一套组合拳吗,不就是沉淀出的可复用的方法论吗?

黑话,咱们也是可以整两句的。

方法论之查看被调用的地方

除了前面两种方法之外,我有时候也会直接看我要阅读部分的方法,在框架中被哪些地方调用了。

比如在我们的 Demo 中,我们要阅读的代码非常的明确,就是 @Transactional 注解。

于是直接看一下这个注解在哪些地方用到了:

有的时候调用的地方会非常的少,甚至只有一两处,那么直接在调用的地方打上断点就对了。

虽然 @Transactional 注解一眼望去也是有很多的调用,但是仔细一看大多是测试类。排除测试类、JavaDoc 里面的备注和自己项目中的使用之后,只剩下很明显的这三处:

看起来很接近真相,但是很遗憾,这里只是在项目启动的时候解析注解而已。和我们要调研的地方,差的还有点远。

这个时候就需要一点经验了,一看苗头不对,立马转换思路。

什么是苗头不对呢?

你在这几个地方打上断点了,只是在项目启动的过程中断点起作用了,发起调用的时候并没有在断点处停下,说明发起调用的时候并不会触发这部分逻辑,苗头不对。

顺着这个思路想,在我的 Demo 中抛出了异常,那么 rollbackFor 和 noRollbackFor 这两个参数大概率是会在调用的时候被用到,对吧?

所以当你去看 rollbackFor 被调用的时候只有我们自己写的业务代码在调用:

怎么办呢?

这个时候就要靠一点运气了。

是的,靠运气。

你都点到 rollbackFor 这个方法来了,你也看了它被调用的地方,在这个过程中你大概率会瞟到几眼它对应的 JavaDoc:

org.springframework.transaction.annotation.Transactional#rollbackFor

然后你会发现在 JavaDoc 里面提到了 rollbackOn 这个方法:

org.springframework.transaction.interceptor.DefaultTransactionAttribute.rollbackOn(Throwable)

到这里一看,你发现这是一个接口,它有好多个实现类:

怎么办呢?

早期的时候,由于不知道具体的实现类是哪个,我是在每个实现类的入口处都打上断点,虽然是笨办法,但是总是能起作用的。

后来我才发现,原来可以直接在接口上打断点:

然后,重启项目,发起调用,第一次会停在我们方法的入口:

F9,跳过当前断点之后,来到了这个地方:

这里就是我前面在接口上打的方法断点,走到了这个实现类中:

org.springframework.transaction.interceptor.DelegatingTransactionAttribute

然后,关键的就来了,我们又有一个调用栈了,又从调用栈中看到一个我们熟悉的东西:

朋友,组合拳这不又打起来了?突破口不就又找到了?

关于“瞟到几眼对应的 JavaDoc ,然后就可能找到突破口”的这个现象,早期对我来说确实是运气,但是现在已经是一个习惯了。一些知名框架的 JavaDoc 真的写的很清楚的,里面隐藏了很多关键信息,而且是最权威的正确信息,读官网文档,比读技术博客稳当的多。

探索答案

前面我介绍的都是找到代码调试突破口的方法。

现在突破口也有了,接下来应该怎么办呢?

很简单,调试,反复的调试。从这个方法开始,一步一步的调试:

org.springframework.transaction.interceptor.TransactionInterceptor#invoke

如果你真的想要有所收获的话,这是一个需要你亲自去动手的步骤,必须要有逐行阅读的一个过程,然后才能知道大概的处理流程。

我就不进行详细解读了,只是把重点给大家画一下:

框起来的部分,就是去执行业务逻辑,然后基于业务逻辑的处理结果,去走不同的逻辑。

抛异常了,走这个方法:completeTransactionAfterThrowing

正常执行完毕了,走这个方法:commitTransactionAfterReturning

所以,我们问题的答案就藏在 completeTransactionAfterThrowing 里面。

继续调试,进入这个方法之后,可以看到它拿到了事务和当前异常相关的信息:

在这个方法里面,大体的逻辑是当标号为 ① 的地方为 true 的时候,就在标号为 ② 的地方回滚事务,否则就在标号为 ③ 的地方提交事务:

因此,标号为 ① 的部分就很重要了,这里面就藏着我们问题的答案。

另外,在这里多说一句,在我们的案例中,这个方法,也就是当前调试的方法是不会回滚的:

而这个方法是会回滚的:

也就是这两个方法在这个地方会走不同的逻辑,所以你在调试的时候遇到 if-else 就需要注意,去构建不同的案例,以覆盖尽量多的代码逻辑。

继续往下调试,会进入到标号为 ① 的 rollbackOn 方法里面,来到这个方法:

org.springframework.transaction.interceptor.RuleBasedTransactionAttribute#rollbackOn

这里,就藏着问题的终极答案,而且这里面的代码逻辑相对比较的绕。

核心逻辑就是通过循环 rollbackRules,这里面装的是我们在代码中配置的回滚规则,在循环体中拿 ex,也就是我们程序抛出的异常,去匹配规则,最后选择一个 winner:

如果 winner 为空,则走默认逻辑。如果是 RuntimeException 或者是 Error 的子类,就要进行回滚:

如果有 winner,判断 winner 是否是不用回滚的配置,如果是,则取反,返回 false,表示不进行回滚:

那么问题的冠军就在于:winner 怎么来的?

答案就藏着这个递归调用中:

一句话描述就是:看当前抛出的异常和配置的规则中的 rollbackFor 和 noRollbackFor 谁距离更近。这里的距离指的是父类和子类之间的关系。

比如,还是这个案例:

我们抛出的是 RuntimeException,它距离 noRollbackFor=RuntimeException.class 为 0。RuntimeException 是 Exception 的子类,所以距离 rollbackFor = Exception.class 为 1。

所以,winner 是 noRollbackFor,能明白吧?

然后,我们再看一下这个案例:

根据前面的“距离”的分析,NullPointerException 是 RuntimeException 的子类,它们之间的距离是 1。而 NullPointerException 到 Exception 的距离是 2:

所以,rollbackFor=RuntimeException.class 这个的距离更短,所以 winner 是 rollbackFor。

而把 winner 放到这个判断中,返回是 true:

return !(winner instanceof NoRollbackRuleAttribute);

所以,这就是它为什么会回滚的原因:

好了,到这里你有可能是晕的,晕就对了,去调试这部分代码,亲自摸一遍,你就搞的明明白白了。

最后,再给“死盯日志”的方法论打个补丁吧。

前面我说了,日志级别调整到 Debug 也许会有意外发现。现在,我要再给你说一句,如果 Debug 没有查到信息,可以试着调整到 trace:

logging.level.root=trace

比如,当我们调整到 trace 之后,就可以看到“ winner 到底是谁”这样的信息了:

当然了,trace 级别下日志更多了。

所以,来,再跟我大声的读一遍:

啃源码的过程,一定是非常枯燥的,特别是啃自己接触不多的框架源码的时候,千头万绪,也得下手去捋,所以一定要耐得住寂寞才行。

作业

我前面主要是试图教你一种阅读源码时,寻找突破点的技能。这个突破点,说白了就是第一个有效的断点到底应该打在哪里。

你用前面我教的方法,也能把 @Cacheable 和 @Async 都玩明白。因为它们的底层逻辑和 @Transactional 是一样的。

所以,现在布置两个作业。

拿着这套组合拳,去上手玩一玩 @Cacheable 和 @Async 吧,沉淀出属于自己的方法论。

@Cacheable:

@Async:

阅读源码技巧 一些知名框架的 JavaDoc 真的写的很清楚的,里面隐藏了很多关键信息,而且是最权威的正确信息,读官网文档,比读技术博客稳当的多。但是需要事先说明的是,阅读源码的方式非常的多,这篇文章只是站在我个人的角度介绍阅读源码的众多方式中的一种,沧海一粟,就像是一片树林里面的一棵树的树干上的一叶叶片的叶脉中的一个小分叉而已。不要觉得自己只是随便看看,不要紧。比如,有人看到标号为 ② 的部分,也就是 AOP 的部分,一想着这玩意我眼熟啊,书上写过 Spring 的事务是基于 AOP 实现的,我去看看这部分代码吧。 阅读详情

相关推荐

【计算摄影】相机成像原理:从光到JPEG图像

本文我们将从最基本的相机成像原理开始论述,再讨论光线进入相机后,经过一系列处理成为JPEG图像的大致流程。

qq_35149975的博客 2万+

提高代码阅读能力的7种方法

原文:7 Ways to Improve Your Code Reading Skills 作者: A. N. M. Bazlur Rahman 翻译:无阻我飞扬 摘要:随着越来越多的公司使用敏捷开发,能够阅读别人的代码比以往显得更重要。这就需要学习一些如何提高这项技能的技巧。本文提供了7种提高代码阅读技巧的方法,以下是译文。在软件开发人员的职位描述中有阅读源代码。然而,这体验...

博客 7056

CondaHTTPError: HTTP 404 NOT FOUND for url

用conda创建新环境时出现问题了。

qq_40713201的博客 1270

如何阅读源代码

     众所周知,要想写出好的程序,除了要经常写之外,还有看看别人是怎么写的,所以读别人的程序是非常重要的;如今是个信息交换十分发达的时代,你可以轻易的就看到顶尖级选手的代码;开源事业蒸蒸日上,确实是所有程序员的福音。但如何阅读别人的代码呢?尤其对于初学者而言,确实是个难题,就像碰到一漂亮的刺猬,实在不知道如何下嘴。        规则一,你读的越多,你就越容易读懂,因为高手写程序的思维都是...

探底 324

史上最全的Logisim运算器实验教程(基于华中科技大学计算机组成原理实验)

本博客是实现了Logisim的运算器设计,有具体的运算器设计的思路和运算器设计的电路,适合一步一步的按照思路做。

qq_62325622的博客 4万+

CTF命令执行绕过实战:从空格过滤到无回显外带的7种核心姿势

命令执行漏洞是Web安全中的常见高危漏洞,其核心原理在于应用程序未对用户输入进行充分过滤,导致攻击者能够注入并执行系统命令。在真实环境中,安全防护措施(如WAF、输入过滤函数)普遍存在,因此漏洞利用的关键技术在于“绕过”这些过滤机制。理解过滤器的运作逻辑(如黑名单、白名单、转义、长度限制)是成功绕过的前提。通过系统学习**空格绕过**、**命令黑名单绕过**、**编码混淆**等基础技巧,并结合**无回显外带**、**反弹Shell**等高级利用链,安全研究人员能够有效应对复杂防护场景。本文以CTFshow

weixin_29315091的博客 370

还不会如何阅读源码?一问教会你阅读源码的方式

正如标题描述的这样,我试图通过这篇文章,教会你如何阅读源码。事情大概是这样的,前段时间,我收到了一个读者发来的类似于这样的示例代码:他说在没有执行代码之前,他也知道前两个为什么一个不会回滚,一个会回滚。因为抛出的异常和 @Transactional 里面的注解呼应上了。但是第三个到底会不会回滚,没有执行之前,他不知道为什么会回滚。执行之后,回滚了,他也不知道为什么回滚了。我告诉他:源码之下无秘密。让他去看看这部分源码,理解它的原理,不然这个地方抛出一个其他的异常,又不知道会不会回滚了。

wdj_yyds的博客 1721

基于YOLO26/11/v8算法的Web目标检测系统,人脸表情识别系统,Django+Vue3 的前后端分离,实现摄像头实时识别,YOLO26/YOLO11/v8 + LLM大模型智能分析,科研必备

在人工智能迈向通用化(AGI)的今天,“视觉感知 + 语言理解”的多模态联合是未来的趋势。单纯的检测画框已经无法满足复杂的业务需求,如何让系统“看懂”画面并进行“思考”,是当前视觉项目的重点。我们知道目标检测是计算机视觉中的重要任务,广泛应用于安防监控、自动驾驶、智能家居等领域。因此本项目将 YOLO 目标检测模型(兼容 YOLO26/v11/v8 系列)与 DeepSeek 等顶流大语言模型(LLM) 进行联合,使用 Django (后端) + Vue3 (前端) 技术栈

在职AI算法工程师,擅长计算机视觉,YOLO目标检测、分割等,擅长web、pyqt界面可视化,好内容持续更新中,来这里跟大家一起学习,共同进步 2846

我阅读源码的一些小技巧

发表于四川以下文章来源于why技术 ,作者why技术技术经验分享公众号你好呀,我是苏三。是的,正如标题描述的这样,我试图通过这篇文章,教会你如何阅读源码。事情大概是这样的,前段时间,我收到了一个读者发来的类似于这样的示例代码:他说他知道这三个案例的回滚情况是这样的:insertTestNoRollbackFor:不会回滚insertTestRollback:会回滚insertTest:会回滚他说在没有执行代码之前,他也知道前两个为什么一个不会回滚,一个会回滚。

竹林幽深 306

Python实现多元线性回归(Multiple Linear Regression)

多元线性回归是一种用于建立多个自变量与因变量之间关系的统计学方法。在多元线性回归中,我们可以通过多个自变量来预测一个因变量的值。每个自变量对因变量的影响可以用回归系数来表示。

优快云 精品推荐 4333

Python爬虫实战:实时爬取东方财富网股票行情

东方财富网实时行情(价格、涨跌幅、成交量等)K线图、分时图、技术指标市盈率、换手率、总市值等指标相比某些收费API,东方财富网页端接口不需要登录、免费、响应快、封装清晰,适合爬虫实践。东方财富网股票数据接口分析实时数据抓取与字段提取数据结构化处理自动化批量抓取多线程加速采集数据可视化展示支持存储为CSV/Excel/数据库。

2201_76125261的博客 1万+

spring 源码系列(零)- 阅读顺序

之所以有这个第“零”篇,是为了让大家对spring体系有着更好的认识,因此在这里推荐大家阅读知乎的大神bravo1988的一篇关于spring的文章,这篇文章很生动具体,可以说是让我茅塞顿开: 传送门:怎么回答面试官:你对Spring的理解? 本篇就只有这么多,后续的几篇会对spring的一些源码进行详细的介绍。 ...

bintoYu的博客 1450

ZY1-02D (ZY1E)多光谱数据预处理

资源一号02D卫星(5米光学卫星)于2019年9月12日成功发射,卫星搭载的两台相机,可有效获取115公里幅宽的9谱段多光谱数据以及60公里幅宽的166谱段高光谱数据,其中全色谱段分辨率可达2.5米、 多光谱为10米、高光谱优于30米,高光谱载荷可见近红外和短波红外光谱分辨率分别达到10纳米和20纳米。

热爱分享,热爱记录 4836

idea构建spring源码,阅读spring-framework源码环境

本篇文章发表于2019-12-11,现在基本的spring源码构建方式基本上有这一篇就足够了,绝对完整 前言 java工程师,在不断学习成长的路上,学习spring源码是必须的,也是成长的毕竟途径 作者本身因为没有人指导,前前后后搞了好几天,终于把spring完整的搞下来了,途中的心酸是真的多!话不多说,直接上干货,这一篇文章基本可以搞定spring源码的构建,对于作者遇到的错误也全部进行了描述。...

gc都收不走的咸鱼 1030

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

GitHub实战学习Python:从源码阅读到开源贡献的完整路径

在编程学习领域,源码阅读是理解技术原理与工程实践的核心方法。通过分析优秀开源项目的代码结构、设计模式和实现逻辑,开发者能够深入掌握编程语言的特性、软件架构思想以及解决实际问题的工程化方案。这种方法不仅有助于巩固语法知识,更能培养解决复杂问题的能力,提升代码质量和工程素养。对于Python开发者而言,GitHub作为全球最大的开源代码库,汇聚了从基础工具到前沿框架的海量真实项目,为这种“基于真实场景”的学习方式提供了绝佳平台。通过系统性地阅读、运行、调试和修改开源代码,学习者可以跨越理论与实践的鸿沟,将知识转

weixin_30323631的博客 319

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

Linux内核实战指南:从源码阅读到性能调优与驱动开发

操作系统内核是计算机系统的核心,负责管理CPU、内存、设备等硬件资源,并为上层应用提供基础服务。其工作原理基于中断、进程调度、虚拟内存等核心机制,通过系统调用接口与用户空间交互。深入理解内核对于解决复杂的系统级问题具有极高的技术价值,尤其在服务器性能优化、嵌入式设备开发和系统稳定性保障等应用场景中至关重要。本文聚焦于Linux内核的工程实践,详细解析了如何利用perf进行性能瓶颈分析,以及遵循内核框架进行设备驱动开发的方法论,为开发者提供了一套从源码探索到问题解决的可落地路径。

weixin_42638178的博客 241

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

6.jdk源码阅读之HashMap(下)

因为是头插法,所以HashMap的顺序已经发生了改变,但线程T2对于发生的一切是不可知的,所以它的指向元素依然没变,如上图展示的那样,T2指向的是A元素,T2.next指向的节点是B元素。因为T1执行完扩容之后B节点的下一个节点是A,而T2线程指向的首节点是A,第二个节点是B,这个顺序刚好和T1扩完容完之后的节点顺序是相反的。与 JDK 7 类似,JDK 8 中的 HashMap 在扩容过程中,如果多个线程同时进行插入操作,可能会导致数据结构的不一致,甚至形成环形链表,导致死循环。

前端、移动端、后端源码级底层原理分享 745

不读前端源码的你,并不清楚自己错过了什么?

相信很多人都试图去看过源码,绝大多数是看不下去,没有及时获得正向反馈是一个原因,或者说,毫无章法的读源码使你并不清楚自己错过了什么?这篇文章将会通过对Vue和jQuery的源码解读,清晰的...

趣谈前端 399

STL源码阅读指南:拆解模板编程难点,高效掌握内存分配器

阅读STL源码是每个C++程序员进阶的必经之路,但面对错综复杂的模板和抽象设计,许多人都会感到困惑甚至挫败。这不仅是技术理解的挑战,更是一场与编程思维模式的博弈。

2501_94209053的博客 351

HashMap源码阅读04

上一篇文章我们呈现了HashMap在扩容时对链表节点的处理过程,这篇文章我们就对其中规律一探究竟。

js_tengzi的博客 399

python是一种解释类型的编程语言-Python入门你要懂哪些?这篇文章总算讲清楚了...

原标题:Python入门你要懂哪些?这篇文章总算讲清楚了 作者 | 小土豆Yuki来源 | 洁癖是一只狗(ID: rookie-dog)从今天开始学习Python,今后会不定期更新Python的相关文章。好了,言归正传,今天我们来看看对于Python初学者,你要知道了解Python的哪些基础知识吧。前言什么是计算机语言计算机就是一台用来计算的机器,人让计算机干什么计算机就得干什么!需要通过计算机的...

weixin_37988176的博客 174

Glide系列第二弹,从源码的角度深入理解Glide的执行流程

深入分析Glide的源码,让你知其然也知其所以然。

郭霖 558

看源码底层,没个几年经验还是算了吧

看源码底层,没个几年经验还是算了吧

大模型学习路线 342

UE5光线追踪源码阅读环境搭建实战指南

光线追踪作为现代实时渲染的核心技术,通过模拟光线物理行为实现全局光照、软阴影与逼真反射,其原理基于光线与场景几何的求交计算及材质着色。在游戏与影视级渲染中,该技术能极大提升视觉真实感与画面沉浸度。要深入理解并优化光线追踪在UE5引擎中的实现,开发者需搭建一个可编译、可调试的本地源码环境。这涉及正确获取UE5源码、配置Visual Studio 2022开发工具链、理解渲染管线与RHI(渲染硬件接口)的分层架构,并针对调试需求优化编译选项。通过本指南,读者将掌握从环境准备到断点调试的全流程,为后续深入追踪光线

weixin_33816300的博客 328
上一篇: 速成算法笔记,我直接手撕1000道Leetcode算法题
下一篇: Alibaba内部疯传《Java权威面试指南》,面试火箭造起来
Java技术那些事儿
博客等级 码龄5年 2306粉丝 2584原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值