- 博客(23)
- 收藏
- 关注
原创 SpringMVC的执行流程
请求到 DispatcherServlet→找方法→执行方法→处理视图→返回响应”,记住这根主线,不管是面试还是排障,都能快速理清思路。如果是 SpringBoot 项目,框架会自动配置等组件,不用手动写配置,更省心,但理解底层流程仍很重要。
2025-09-16 22:48:46
951
原创 SpringBoot的自动配置原理
方法中,它会返回 “需要生效的自动配置类全限定名数组”。这些类对应了 Web、数据库、日志等常见场景,是自动配置的 “候选池”。系列条件注解 **,只有满足条件的类才会被加载到 IoC 容器。候选列表中的自动配置类并非全部生效,每个类上都标注了 **,就是负责 “筛选哪些自动配置类需要生效” 的核心类。SpringBoot 自动配置的一切,都从启动类上的。例如,若手动配置了 Druid 数据源,可排除默认的。自动配置类不仅会创建 Bean,还会读取。,2.7 + 简化为直接写配置类路径。
2025-09-16 22:28:43
1454
原创 String、StringBuilder和StringBuffer的区别
在 Java 开发中,字符串处理是日常编码中最频繁的操作之一。String、StringBuilder 和 StringBuffer 这三个类虽然都用于操作字符串,但在性能、线程安全性和使用场景上存在显著差异。String 类是 Java 中最基础的字符串类,其底层实现具有不可变性:存储结构:在 JDK 8 及之前,String 内部通过 private final char value[] 数组存储字符;JDK 9 及以上改为 byte[] 数组(根据编码自动选择存储方式,节省内存)。 不可变性:valu
2025-09-15 19:41:51
370
原创 Java 线程安全实现:从基础原理到实战方案
JUC(java.util.concurrent)是 Java 官方提供的并发工具箱,封装了线程安全的集合、线程池、同步工具,无需手动处理锁逻辑,开发效率更高。ReentrantLock 是 JUC 包提供的显式锁,需手动创建锁对象、手动加锁 / 释放锁,支持更多高级特性,适合复杂场景。优点:使用简单,无需手动释放锁(代码执行完或抛异常时自动释放),支持 “可重入”(同一线程可多次获取同一把锁);缺点:不支持中断等待、超时获取锁等高级功能,是非公平锁(不保证等待时间长的线程先获取锁)。
2025-09-15 10:28:56
896
原创 HashMap 核心知识点总结
计算索引:用 “扰动后的哈希值 & 数组长度 - 1”(等价于 “哈希值 % 数组长度”,但位运算更快),且数组长度必须是 2 的幂(保证 “数组长度 - 1” 的二进制全为 1,索引分布更均匀)。HashMap:基于哈希表(数组 + 链表 / 红黑树),非线程安全,Key 允许 1 个 null、Value 允许多个 null,无序,时间复杂度接近 O (1);Hashtable:基于哈希表,线程安全(全表加锁),Key/Value 都不允许 null,无序,性能低,已被淘汰;
2025-09-15 10:12:22
868
原创 数据库事务详解
(如 “查询库存 < 10 的商品”),期间另一个事务(T2)插入 / 删除了符合该范围的新数据并提交,导致 T1 前后两次查询的 “结果行数不一致”(像出现了 “幻影” 一样)。核心问题:“同一事务内的读一致性” 被破坏 —— 事务期望 “一旦读取某数据,后续再读该数据时结果不变”,但实际被其他已提交事务修改。3.可重复读:一个事务在执行的过程中,多次读取同一数据结果一致,可避免脏读和不可重复读,但幻读仍有可能发生。核心问题:读的是 “临时数据”,数据最终可能被撤销,导致 T1 基于脏数据做的决策错误。
2025-09-11 17:35:18
757
原创 MySQL知识点总结
数据库数据存在磁盘,磁盘 I/O 成本远高于内存。B+Tree 是多路平衡树,一个节点能存大量键值和子节点指针,一次磁盘读取可获取更多索引信息,极大减少 I/O 次数。红黑树是二叉树,节点分支少,要存同样多数据,树更高,I/O 次数多,效率低。
2025-09-11 17:01:28
1194
原创 Java并发核心知识点梳理
悲观锁的实现: synchronized ReentrantLock乐观锁的实现: CAS非自旋锁:属于悲观锁的实现方式,核心是 “加锁 + 阻塞”。线程尝试获取锁时,若锁已被占用,会立即放弃 CPU,进入阻塞状态(被挂起),直到锁释放后被唤醒。的重量级锁、在竞争激烈时的阻塞状态,都是典型的非自旋锁 —— 它们明确依赖 “锁” 的独占性,且竞争失败时必然阻塞。乐观锁:核心是 “无锁 + 自旋重试”,本质是 “不主动加锁,靠冲突检测保证安全”。线程操作数据时不先加锁,而是假设不会冲突,直接修改。
2025-09-03 23:08:07
1082
原创 Java线程池核心知识
核心线程数=0,最大线程数=Integer.MAX_VALUE,没有核心线程,所有的线程都是非核心线程,非核心线程处理完任务后,若 60 秒内没有新任务,就会被销毁。核心线程数=最大线程数=nThreads,意味着不会创建临时线程(非核心线程),因此 “空闲线程存活时间” 参数实际无效(核心线程默认不会因空闲销毁)不会创建非核心线程–》不会新增:即使有很多任务,所有的线程都在忙碌 新任务也只会进入队列等待。④工作队列 :用于缓存任务的阻塞队列,当核心线程都在忙时,新任务会先进入队列等待。
2025-09-03 22:15:57
714
原创 Java程序员必懂的JVM体系
先让父加载器尝试加载,父加载器无法加载时,子加载器才自己尝试加载”。这里的 “双亲” 并不是指 “父亲和母亲”,而是指 “上级加载器”。启动类加载器(最顶层):负责加载 Java 核心类库(如java.lang包下的类)扩展类加载器:负责加载扩展目录中的类应用程序类加载器:负责加载项目 classpath 下的类自定义类加载器(最底层):开发者自己定义的类加载器JVM 中类加载器的父子关系是固定的链式结构启动类加载器 → 扩展类加载器 → 应用程序类加载器 → 自定义类加载器。
2025-09-02 15:18:35
954
原创 Redis核心知识梳理
Redis 是一款开源的高性能键值对数据库,核心特点是基于内存存储,因此读写速度极快(每秒可达十万级操作),同时支持数据持久化到磁盘。Redis 常作为缓存减轻数据库压力(如存储高频访问的商品数据),也用于分布式会话、排行榜等业务,是提升系统性能的核心中间件。Redis 的持久化是指将内存中的数据定期保存到磁盘的机制,目的是防止服务器重启或断电时数据丢失,平衡了 Redis “基于内存” 的高性能与数据可靠性。
2025-09-02 10:56:49
654
原创 对于synchronized的理解
Monitor结构:WaitSet EntryList Owner 假设有一个线程进来执行 ,它会将锁对象和Monitor关联 ,判断Owner是否为null ,如果为null, 当前线程就拥有了对象锁 Owner只能关联一个线程 ,不为null要去EntryList中等待,当一个线程调用了wait方法就会处于等待状态 会把等待的线程放WaitSet中。Monitor:当锁升级到 重量级锁 时,依赖 Monitor(监视器锁) 实现同步。对象头:存储锁状态,实现锁升级。对象头和Monitor。
2025-08-14 19:32:27
431
原创 对于ThreadLocal的理解
每一个ThreadLocal维护了一个ThreadLocalMap,在ThreadLocalMap中的Entry对象继承了WeakReference,其中key为ThreadLocal对象的弱引用,value为线程变量的副本,如果内存不够,会被回收。每个Entry对象的key为ThreadLocal对象,value为存储的数据。remove () 方法中会把 Entry 中的 key 和 value 都设置成 null,这样就能被 GC 及时回收,无需触发额外的清理机制,所以它能解决内存泄漏问题。
2025-08-13 19:59:21
308
原创 Bean的生命周期
1.初始化方法优先级:InitializingBean.afterPropertiesSet() 的执行优先级 高于 自定义 init-method。2.销毁方法优先级:DisposableBean.destroy() 的执行优先级 高于 自定义 destroy-method。3.BeanPostProcessor 的作用: 对Bean 进行方法增强,它是 Spring AOP 实现的底层机制之一。对所有 Bean 生效(包括 User),可在初始化前后插入自定义逻辑.4.结果。
2025-07-27 14:16:34
1229
原创 MyBatis的运行原理
MyBatis在启动时,会加载核心配置文件(mybatis-config.xml)和映射文件(XXXMapper.xml或注解) 包含数据源、事务等,映射文件定义SQL语句。通过SqlSessionFactory.openSession()创建SqlSession对象,SqlSession代表一次数据库会话,非线程安全。通过SqlSession.getMapper(XXXMapper.class)获取Mapper接口的动态代理对象(基于JDK动态代理)。代理的作用是拦截方法调用,匹配对应的SQL。
2025-07-21 19:25:01
451
原创 字符串String基本知识2
在 Java 中,String 类使用字符数组 char[] 存储字符,但该数组被 final修饰,这意味着一旦初始化,它的引用就不能被修改。如果对字符串进行修改操作,实际上是创建了一个新的字符串对象,而不是修改原有的字符串对象。2.trim()移除首尾空白字符,空白字符包括\t\r\n , isEmpty()判断字符串是否为空字符串。1.startsWith()和endsWith()是用于判断字符串是否以指定字符串开头或结尾。3.字符串的替换:replace() ,replaceAll()
2025-01-20 23:27:47
592
原创 static关键字的用法
与普通的实例成员变量不同,静态成员变量属于类本身,而不是类的实例。静态内部类是嵌套在另一个类中的类,并且使用 static 关键字进行修饰。它不依赖于外部类的实例,可以直接被实例化,并且只能访问外部类的静态成员。静态代码块在类加载时执行,且只执行一次,无论创建多少个该类的对象,静态代码块都只会执行一次。②访问方式:静态成员变量可以通过类名直接访问,也可以通过对象实例访问,但通常建议使用类名访问,因为它属于类的特性,而不是某个对象的特性。可以在不创建类的实例的情况下直接调用静态方法,通过类名来调用。
2025-01-20 22:15:11
366
原创 关于StringBuilder扩容机制的理解
创建StringBuilder时,初始容量为16。在for循环中,每次调用append方法时,计算minimumCapacity。前五次循环时,minimumCapacity未超过初始容量16,因此不需要扩容。第六次循环时,minimumCapacity超过了初始容量,触发扩容,新容量为34(16*2+2)。
2025-01-20 00:21:01
1199
原创 抽象类和接口
在Java中,—个没有方法体的方法应该定义为抽象方法,而类中如果有抽象方法,该类必须定义为抽象类接口是Java中一种抽象类型,它只包含抽象方法(Java8开始可以包含default方法和静态方法)和常量。接口的定义使用interface关键字,另外,接口定义的所有方法默认都是publicabstract,所以这两个修饰符不需要显示的定义出来(写或不写效果都一样)。当一个具体的class去实现一个interface时,需要使用implements关键字。
2025-01-18 20:22:12
1203
原创 面向对象知识点
实现某个具体功能的方法,是一系列步骤的总和,方法是若干“代码语句片段”的集合,完成个具体的功能,并设置直观易懂的名字,方便后期在程序中去“使用(调用)”。修饰符static返回值类型方法名(参数类型参数名){return返回值;
2025-01-18 15:02:06
695
原创 字符串String的基本知识1
Java的字符类型char是基本类型,字符串类型String是引用类型基本类型的变量是“持有”某个数值,引用类型的变量是“指向”某个对象引用类型的变量可以是空值null要区分空值null和空字符串""
2025-01-13 02:04:18
458
原创 Java初识数组
2.静态初始化:数据类型[]数组名=new数据类型[]{元素1,元素2,……eg:String[]names=newString[]{“小明”,“小王”,“小张”}3.静态省略初始化:数据类型[]数组名={元素1,元素2,;eg:String[]names2={“小明”,“小王”,“小张”};1.动态初始化:数据类型[]数组名=new数据类型[长度]1.取值:数据类型变量名=数组名[下标]1.第一种方式:数据类型[]变量名;2.赋值:数组名[下标]=对应类型的值。
2025-01-13 01:34:22
345
1
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅