- 博客(59)
- 收藏
- 关注
原创 Spring事务实现原理深度解析:从源码到架构全面剖析
Spring事务通过AOP代理、事务管理器、同步机制等组件提供了强大而灵活的事务管理能力。本文将重点剖析事务传播机制的实现原理,包括事务管理器的架构、AOP代理原理、事务同步机制、传播行为实现细节等核心概念。Spring事务管理建立在三个核心接口之上,这些接口构成了整个事务管理体系的抽象层:1.2 事务管理器实现层次结构Spring提供了多种事务管理器实现,形成了清晰的继承体系:1.3 数据源事务管理器实现是Spring中最常用的事务管理器实现,它管理JDBC连接的事务:2. Spring事务AO
2025-11-12 17:32:26
644
转载 并发:AQS源码解析
AQS即的简称,翻译过来就是抽象队列同步器的意思,由Doug Lea大神开发的。说他抽象是因为它提供的是一个基于队列的同步器框架,定义了一些基础功能方法(控制状态变量,获取和释放同步状态方法以及入队出队操作等),具体场景使用只需要根据需要实现对应的方法即可。我们在锁(比如ReentrantLock)、并发工具类(比如CountDownLatch)都可以看到内部类继承了,也就是说AQS才是这些类的基石。说了这么多,感觉把抽象说的越抽象了,下面我们从几个栗子入手吧。
2025-09-15 17:05:09
75
原创 并发:如何设计线程安全的类
明确状态范围:识别所有构成对象状态的变量(包括引用对象的字段)。优先封装与封闭:通过实例封闭将状态限制在类内部,用内部锁协调访问。善用线程安全组件:尽量委托给线程安全的组件(如),减少手动同步。处理状态依赖:当组件状态存在依赖时,需额外加锁保证复合操作的原子性。安全发布对象:避免对象逸出,确保在完全初始化后再发布,使用finalvolatile或同步机制保证可见性。通过这些原则,可将复杂对象的线程安全问题分解为更小的、可管理的部分,从而降低并发编程的难度,提高代码的可靠性。
2025-09-12 16:40:32
938
原创 并发:使用volatile和不可变性实现线程安全
Java并发编程实战》中的展示了volatile来实现线程安全。解决了简单缓存实现中可能出现的线程安全问题,同时避免了全量同步带来的性能开销。
2025-09-12 10:57:41
643
原创 Leetcode77:组合问题
LeetCode 77题(组合)要求从1到n中选择k个数字的所有可能组合,且组合中的元素不能重复,顺序不影响组合的唯一性(例如[1,2]和[2,1]视为同一个组合)。这是一个典型的组合问题,适合用回溯算法解决。
2025-09-06 13:29:00
492
原创 LeetCode15:三数之和
算法的时间复杂度为O(n²),其中排序占O(n log n),主体双指针遍历占O(n²);空间复杂度为O(1)(不包括存储结果的空间)。
2025-09-06 11:46:52
299
原创 机器学习:贝叶斯派和频率派
频率派和贝叶斯派分别给出了一系列的机器学习算法。频率派的观点导出了一系列的统计机器学习算法而贝叶斯派导出了概率图理论。在应用频率派的 MLE 方法时最优化理论占有重要地位。而贝叶斯派的算法无论是后验概率的建模还是应用这个后验进行推断时积分占有重要地位。因此采样积分方法如 MCMC 有很多应用。
2025-08-25 23:28:38
820
原创 Effective Java笔记:用接口模拟可扩展的枚举
Java 的枚举类型本质上是final的,无法通过继承直接扩展。例如,若有一个表示基本算术操作的枚举(包含ADDSUBTRACT),后续若需添加新操作(如MULTIPLYDIVIDE),无法直接扩展原有枚举。:如何在不修改原有代码的情况下,扩展枚举的功能?通过定义一个公共接口,让多个枚举类实现该接口,客户端代码通过接口类型操作枚举实例,实现多态。Operation接口声明所有枚举需要实现的核心方法。基础枚举实现接口,提供默认操作(如加、减)。新枚举同样实现Operation接口,添加新操作(如乘、除)。
2025-08-25 16:19:02
685
原创 Effective Java笔记:enum 代替 int 常量
ALIPAY(amount -> System.out.println("使用支付宝支付: ¥" + amount)),WECHAT(amount -> System.out.println("使用微信支付: ¥" + amount)),UNIONPAY(amount -> System.out.println("使用银联支付: ¥" + amount));// 测试结果:使用支付宝支付: ¥199.9使用微信支付: ¥88.8。
2025-08-25 11:37:52
556
原创 Effective Java笔记:优先考虑类型安全的异构容器
指能够存储不同类型对象的容器(与普通泛型容器如List<T>只能存储单一类型T不同)。而则是在编译时就能保证存储和获取对象的类型一致性,避免运行时的实现。这类容器在依赖注入、序列化框架、配置管理等场景中广泛应用,其核心价值是在灵活存储多类型对象的同时,通过编译期检查规避类型错误。
2025-08-22 11:24:41
1339
原创 Effective Java笔记:显式创建泛型数组是非法的,用泛型可 变参数声明方法却是合法的
场景本质问题为何合法/非法?显式创建泛型数组无法在运行时保证数组元素的类型安全非法:直接违反数组的运行时类型检查特性,风险不可控。泛型可变参数方法底层依赖泛型数组,但使用场景更受限合法:为了易用性妥协,通过编译器警告和转移安全责任给开发者。
2025-08-21 10:31:02
518
原创 Effective Java笔记:请不要使用原生态类型
在《Effective Java》的中,Joshua Bloch 强调了「」这一规则,并通过丰富的实例和详细分析,展示了泛型如何改善代码的表达力、类型安全性和灵活性。泛型是 Java 的一大飞跃,使得开发者能够编写更加通用和安全的代码。在 Java 中,原始类型(Raw Types) 是泛型引入之前所使用的一种写法,它不对类型进行参数化处理。例如,List是原始类型,而是泛型的用法。为了规避这些问题,应该尽量使用泛型代替原始类型。Stack<E>。
2025-08-18 11:30:50
449
原创 Effective Java笔记:限制源文件为单个顶级类
而开发者在写代码时,可能会误以为这些包级私有类是封装的,从而在同一包的其他类中错误地使用了它们。当文件中包含多个类时,开发者必须深入阅读代码才能弄清楚文件中到底有哪些类以及它们的用途。如果某些类确实与顶级类紧密关联,只在其中范围使用,使用嵌套类代替顶级类。在源文件中定义多个顶级类可能导致文件管理的混乱,特别是在跨包引用的情况下。将每个顶级类放在单独的文件中,能让团队更好地管理和协作,减少冲突,同时提升代码审查的效率。的顶级类,那么源文件的名称必须与该类的名称完全相同(包括大小写)。且不嵌套在其他类中的类。
2025-08-18 10:19:05
355
原创 Effective Java笔记:静态成员类优于非静态成员类
这一点在大规模系统中尤为重要,尤其是当类的引用关系复杂时,非静态成员类容易在不经意间导致外部类实例无法被垃圾回收。如果成员类并不需要访问外部类的非静态成员(属性或方法),将其设计为非静态类,会引入不必要的耦合。尽管静态成员类通常是更优的设计选择,但有时我们仍然会使用非静态成员类。静态成员类的实例化速度更快,因为它不需要与外部类实例挂钩,且不需要额外存储外部类实例的引用。当内部类必须访问外部类的某些状态(实例变量或非静态方法)时,非静态成员类是合理的选择。静态成员类的使用方式更简单,不需要关联外部类实例。
2025-08-15 17:28:40
807
原创 Effective Java笔记:类层次优于标签类
标签类(Tagged Class)是一种反面设计模式,通常通过一个单一的类表示多种逻辑和行为,并使用“标签字段”来区分每种逻辑。// 标签字段,标识形状的类型// 用于矩形的属性// 用于圆形的属性// 构造圆// 构造矩形// 计算面积(根据标签字段的类型分支处理)default:在这个例子中,Figure使用一个Shape标签字段来标记它是一个矩形还是一个圆形,然后在构造器和方法中使用switch或if-else的判断逻辑来操作不同的字段。标签类设计的缺陷。
2025-08-15 17:04:56
469
原创 Effective Java笔记:为后代设计接口
方法的新增行为在实现类中是"隐形的",它可能会在实现类中引入行为变化,而开发或维护人员不一定意识到这些变化。例如,新增的方法可能需要特定的上下文或数据,而某些实现类可能没有这些条件。如果需要在现有接口上扩展新功能,而这个功能对现有实现类的意义不强,可以选择创建一个新接口,并用它补充现有接口。如果需要为接口提供某些通用功能,可以设计一个抽象类来实现接口,同时为需要默认行为的子类提供基本实现。接口应该是一个明确的"契约",只是声明 “对象必须支持的方法”,具体如何实现则由实现类负责。的使用提出了重要的建议。
2025-08-15 16:39:48
725
原创 Effective Java笔记:接口优于抽象类
在 《Effective Java 第三版》中,作者 Joshua Bloch 对“接口优于抽象类”这一原则有着深入的探讨。在理解“接口优于抽象类”之前,我们需要明确二者的本质区别:书中的核心观点是:接口提供了更大的灵活性、更广泛的适用性以及更好的未来兼容性。因此,Joshua Bloch 在条目20中推荐开发者优先选择接口,原因如下:示例:接口的多重继承相比抽象类,接口让一个类可以轻松拥有“多个行为”(复合式能力),而不需要受到单继承的限制。书中例子常见的场景: 和 模式相比抽象类,接口更加关注对
2025-08-15 15:59:39
934
原创 Effective Java笔记:要么设计继承并提供文档说明,要么禁止继承
这个观点强调的是在使用继承时,设计者必须明确其意图,并为继承行为提供清晰的文档说明来指导子类的扩展。如果无法提供合适的设计和说明,那么禁止继承反而是更好的选择。在很多情况下,复合是一种可以代替继承的更安全的设计模式(见之前“复合优于继承”的讨论)。通过组合其他类而非继承,可以提高类的可维护性和封装性。当一个类的实现很容易因子类滥用而出问题时,应尽可能明确哪些部分是封闭的(不可重写),哪些部分开放给子类(可重写)。对于工具类(跟逻辑无关,只保存一些静态方法),禁止继承是一种推荐的设计方法。
2025-08-15 13:51:48
587
原创 Effective Java笔记:复合优先于继承
强耦合是指子类和父类直接绑定在了一起,当父类的内部实现发生变化时,子类可能会无意中受到影响。例如,父类新增一个字段或修改一个方法,可能导致子类的行为和逻辑不再正确。继承是通过“Is-A”关系(从逻辑上表示子类是父类的一种子类型)来复用父类的代码。的值,改动父类 API 的隐含语义,可能引发意外的使用错误。继承行为是静态的,即在编译时确定了父子关系(依赖于静态类型),无法在运行时动态扩展功能。继承使用**“Is-A”**语义:一个对象可以被看作是它父类的一种类型。在继承关系中,子类可以直接访问父类的。
2025-08-15 11:28:01
1110
原创 Effective Java笔记:使可变性最小化
Effective Java》中明确指出,不可变对象的设计是代码安全性和可维护性的基础。在很多场景下,我们应尽可能减少类的可变性,甚至设计为完全不可变。尽管不可变类是优选,但在某些场景中,我们需要使用可变类(如对象需要频繁更新)。当对象的状态是不可变的时候,程序中许多异常状态根本不会发生。不可变对象提供了一种明确的行为保证:它们的状态不会发生变化。如果类中包含可变对象,不要将这些引用直接公开,而应提供不可变的视图或防御性拷贝。不可变对象的状态不能被更改,因此可以安全地在线程之间共享,无需显式同步。
2025-08-14 18:04:26
505
原创 Effective Java笔记:要在公有类而非公有域中使用访问方法
如果直接使用公有域,外界代码会直接访问或修改类的成员变量,其使用方式可能依赖这些变量的当前实现。一旦你需要修改类的实现(比如改变成员变量的结构或语义),就会破坏依赖这些字段的代码。在面向对象编程中的封装原则(encapsulation)强调,类的实现细节应该对外界隐藏,而只通过控制良好的接口进行交互。将数据的内部表示与访问方式解耦,如果未来修改了内部逻辑或存储方式,只需调整访问器方法,而无需修改客户端代码。),并提供公有的访问方法(getter 和 setter)来控制对这些变量的访问和修改。
2025-08-14 15:18:17
703
原创 Effective Java笔记:使类和成员的可访问性最小化
即通过隐藏实现细节,仅暴露必要的接口,来降低模块之间的耦合性。在设计公共类时,需要特别小心它的 API,因为一旦发布,修改它可能会破坏跟它交互的代码。在声明类和成员时,尽可能限制其访问权限,使其可见性最小化。字段是不可变的,但它仍然破坏了封装,因为类的实现细节(如错误代码字符串)对外公开。修饰的数组或集合使得对内部数据的修改权限不受控制,这是一个常见的过失设计。实现类(如接口的具体实现)通常是特定于模块的细节,不应直接暴露给外部。,允许子类复用父类的逻辑,但仍需谨慎设计受保护的成员。
2025-08-14 14:30:57
1050
原创 Effective Java笔记:考虑实现 Comparable 接口
即"自然顺序"(natural ordering)。只能定义一种排序逻辑),此时可以使用静态工厂方法结合。和静态工厂方法,可以实现更加灵活的排序逻辑,而不会被。类中,我们定义一个静态工厂方法用于生成按年龄排序的。当我们需要对同一类的实例基于不同属性排序(但。中,直接用两个整数相减可能产生溢出问题。违反这些逻辑将导致排序行为异常,例如在。的方式,会使代码更清晰且易维护。接口时,目的是让对象具有一种。,以动态灵活地实现多重排序。当我们使用 Java 的。以下是按姓名进行排序的。此外,通过结合自定义的。
2025-08-13 17:10:55
707
原创 Effective Java笔记:谨慎地覆盖 clone
接口最初是设计为一种对对象进行拷贝的方法。然而,实际使用中因其存在浅拷贝问题、多态问题、异常处理复杂性等缺陷,拷贝构造器是一种特殊的构造器,用于创建一个新对象,并通过另一个对象来初始化其内容。修改克隆对象中的引用类型字段会反作用于原对象,可能导致错误或非预期的共享行为。方法中调用被子类覆盖的方法,可能造成运行时错误。方法时,需要遵循一些最佳实践,以尽量规避其固有的隐患。时需要特别小心,因为其内部存储的对象通常是引用类型。例如,第三方库需要类实现。在某些情况下,你可能需要使用。集合类或类似容器的数据结构在。
2025-08-13 16:42:51
332
原创 Effective Java笔记 :覆盖 equals 时请遵守通用约定
在《Effective Java》中,是一个重要的指导原则。equals方法是 Java 对象中最核心的方法之一,正确地覆盖它不仅可以让程序运行更可靠,还能避免由于设计错误导致的潜在问题,例如违反对称性或一致性等。下面我们会详细讲解覆盖equals方法的通用约定、注意事项、以及一个示例实现。equalsequals方法在这一默认实现检查两个对象是否是(内存地址是否相同)。
2025-08-13 11:45:11
615
原创 Effective Java笔记:优先考虑依赖注入来引用资源
子类,或者需要延迟构造(Lazy Initialization),传统构造方法难以高效实现。如果想动态决定实例化逻辑(如:参数配置、动态初始化),则需要大量冗余代码。在传统的工厂设计模式中,创建一个 Mosaic 通常会直接传入一个具体的。的实例(可能是某个具体子类的实例,而非Tile本身)。这个方法是一个静态工厂方法,用于创建一个。是标准函数式接口,极其方便配合。等 Java 8+ 的特性使用。是由这些方块拼接起来的大图片。实例,可以根据需求动态提供。的实现只需要知道如何生成。如果需要按需生成不同的。
2025-08-12 17:34:13
263
原创 Effective Java笔记:用私有构造器或者枚举类型强化 Singleton 属性
是一个经典的设计模式和实践建议。Singleton(单例模式)是很常见的设计模式,用于确保一个类全局只有一个实例存在。很多早期的实现方式,比如懒加载的双重检查锁定,会出现线程安全问题。Singleton 模式确保某个类只有一个实例,并提供全局访问点访问它。懒汉式在第一次需要时实例化对象,可以节省内存,适合对象创建代价较高、使用频率较低的场景。对于单纯的全局实例管理(例如工具类、配置类),JVM 本身的强大枚举机制已经完全足够。饿汉式是在类加载时就创建好 Singleton 实例,以确保线程安全。
2025-08-12 16:56:35
888
原创 Effective Java笔记:遇到多个构造器参数时要考虑使用构建器
是一个专门用于弥补多参数构造器弊端的设计模式。通过引入一个 “构建器类(Builder)”,可以灵活地构造复杂对象,同时具有更好的可读性和易用性。假设我们设计一个用来表示食品配置信息的类。在《Effective Java》的。来替代传统的构造器或静态工厂方法。
2025-08-12 16:38:54
473
原创 Effective Java笔记:静态工厂方法代替构造器
是《Effective Java》(第3版) 中非常重要的一条建议,** 避免直接使用构造器,优先考虑静态工厂方法**。或通过更高层次的抽象解决扩展问题,往往取决于具体需求和设计情境。提供一个更高层次的抽象,通过接口定义行为,由工厂类动态决定返回具体的实现。可以轻松复用接口实现,且隐藏子类,增强了灵活性。书中强调:与直接使用构造器相比,静态工厂方法提供了更大的灵活性和可维护性。:相比构造器,静态工厂方法不能靠 “new” 关键字直观发现,需通过文档了解其用法。通过传入的参数,动态决定返回哪个具体实现。
2025-08-12 15:40:02
554
原创 Netty中NioEventLoop源码解析
类是 Netty 4.1 中实现 Reactor 模型的单线程事件循环类,继承自 ,负责处理 I/O 事件、任务调度和事件分发。以下是类中定义的所有字段,逐一解析其作用和实现细节。定义:初始化:硬编码为 256。作用:使用场景:防止频繁调用 ,优化性能。设计理念:定义:类型:,静态常量。修饰符:,不可修改。初始化:通过 读取系统属性,默认为 。作用:使用场景:若优化启用(),使用 (基于数组)替换默认 ,提升 处理效率。设计理念:定义:初始化:硬编码为 3。作用
2025-08-02 11:42:54
1388
原创 Netty是如何解决epoll CPU占用100%问题的
epoll 100% CPU 问题由 Java NIO 的空轮询引起,通常源于epoll_wait的异常返回。Netty 的解决方案空轮询检测:通过selectCnt计数器检测连续空轮询,超过阈值(默认 512)触发。重建 Selector:创建新Selector,重新注册Channel,解决epoll问题。动态 select 策略:根据任务状态选择selectNow或,减少不必要调用。自适应超时:动态调整select超时时间,降低空轮询影响。异常处理:捕获等,保持循环稳定。在中的作用。
2025-07-30 22:09:59
981
原创 Netty中FastThreadLocal解读
是 Netty 中提供的高性能线程局部存储(Thread-Local Storage)实现,位于包。它是 Java 标准库的替代品,旨在优化性能,减少内存分配和访问开销,特别适合 Netty 的高并发异步框架。依赖实现高效存储,广泛用于EventLoop、对象池(如Recycler)、和性能敏感场景。
2025-07-29 21:42:12
979
原创 Netty中InternalThreadLocalMap的作用
是 Netty 内部工具类,用于。它替代了 Java 标准库的,为 Netty 的高性能异步框架提供了优化的线程局部变量管理机制。该类在 Netty 的运行时环境中扮演关键角色,特别是在事件循环(EventLoop)、对象池(Recycler)、随机数生成和其他性能敏感场景中。Recycler。
2025-07-29 21:28:09
1222
原创 Netty中trySuccess和setSuccess的区别
trySuccess包类方法签名返回值booleantrue表示成功设置结果,false表示设置失败)描述:尝试将Promise设置为成功状态并存储结果。如果Promise尚未完成(即result字段为null),则设置成功并返回true;如果已完成(成功或失败),则返回false,不修改状态。
2025-07-28 23:05:22
910
原创 Java中的协变、逆变
通过通配符,Java 泛型在保证类型安全的前提下,提供了一定的灵活性。如果允许将 “苹果篮子” 当作 “水果篮子”,就可能向其中放入香蕉,导致类型错误。),你知道里面装的是水果(或其子类),但不确定具体是哪种水果。),你知道它可以装苹果(或其父类,如水果、食物)。是泛型系统中的重要概念,用于描述子类型如何在复杂类型(如集合)中传递。类型),但不能向其中添加任何水果(因为不知道篮子的具体类型)。子类的列表”,而是 “某个具体子类的列表”。,则不使用通配符,直接指定具体类型。),因为不确定篮子的具体类型。
2025-07-28 14:15:06
731
原创 Netty中 ? extends Future<? super V>这种的写法的理解
/ 写入 Integer(Number 的子类)try {// 写入 Number 的子类});// 监听结果@Override} else {});类型关系:V 是 Number,?super Number 包括 Number 或 Object。F 是 Future(DefaultPromise)。外层通配符super Number> 允许监听器处理 Future。内层通配符。
2025-07-27 12:43:22
1063
原创 Netty中DefaultChannelPipeline源码解读
DefaultChannelPipeline 是 ChannelPipeline 接口的默认实现,位于 io.netty.channel 包中。它为每个 Channel 提供一个事件处理管道,管理一组 ChannelHandler,通过 ChannelHandlerContext 形成双向链表,处理入站(如 channelRead)和出站(如 write)事件。源码位置事件传播:协调入站和出站事件的传播。动态管理:支持运行时添加、移除或替换 ChannelHandler。上下文管理。
2025-07-26 22:20:56
688
原创 Netty中AbstractChannelHandlerContext源码分析
AbstractChannelHandlerContext 是 ChannelHandlerContext 的抽象实现,位于 io.netty.channel 包中。它实现了 ChannelHandlerContext、ChannelInboundInvoker 和 ChannelOutboundInvoker 接口,提供事件传播、上下文访问和管道操作的核心功能。源码位置。
2025-07-26 20:29:55
983
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅