导图社区 Java知识体系思维导图
这是一篇关于Java知识体系思维导图的思维导图,主要内容包括:工具链与DevOps,大数据,系统设计与性能优化,框架与中间件,Java高级,Java基础。
编辑于2025-09-02 11:31:33Java知识体系思维导图
Java基础
语法基础
数据类型(基本类型、包装类)
基本数据类型
整数类型
byte:1字节,-128~127,0
short:2字节,-32786~32767,0
int:4字节,-2^31 ~ (2^31)-1,0
long:8字节,-2^63 ~ (2^63)-1,0L
浮点类型
float:4字节,10^38,0.0F
double:8字节,10^308,0.0
字符类型
char:2字节,0 ~ 65535,'\u0'
布尔类型
boolean:1字节,true~false,false
包装类
Object
Number
整数类型
Byte:Number,-128~127,null
Short:Number,-32786~32767,null
Integer:Number,-2^31 ~ (2^31)-1,null
Long:Number,-2^63 ~ (2^63)-1,null
浮点类型
Float:Number,10^38,null
Double:Number,10^308,null
字符类型
Character:Object,0 ~ 65535,null
布尔类型
Boolean:Object,true~false,null
运算符、流程控制(if/switch/循环)
运算符
算术运算符
普通运算符:+、-、*、/、%
自增/自减:++i(先增后赋值)、i++(先赋值后增)
关系运算符
==(等于)、!=(不等于)、>、<、>=、<=
返回布尔值(true/false),用于条件判断。
逻辑运算符
短路运算
&&:左右同为真,结果为真;左为假,则不计算右侧
||:左右同为假,结果为假;左为真,则不计算右侧
非短路运算
&:左右同为真,结果为真,且左右均要计算
|:左右同为真,结果为真,且左右均要计算
^:左右不同为真,结果为真,且左右均要计算
!:结果取反
位运算符
&:按位与
|:按位或
^:按位异或
~:取反
<<:有符号左移,右侧补0
>>:有符号右移,左侧补符号位,负数越移越大,正数越移越小
<<<:无符号左移
>>>:无符号右移,左侧补0,负数会变成极大正数
赋值运算符
条件运算符
其他运算符
流程控制
顺序结构
分支结构
循环结构
跳转控制
注意事项
运算符优先级
括号 () > 算术运算符 > 关系运算符 > 逻辑运算符 > 赋值运算符
短路逻辑的优势
&&:逻辑与,左操作数为假时跳过右侧
||:逻辑或,左操作数为真时跳过右侧
浮点数比较
switch的穿透性
字符串(String、StringBuilder、StringBuffer)
面向对象(OOP)
四大特性:封装、继承、多态、抽象
封装
核心目标
数据安全与模块化
定义
封装,即隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别。
解释
防止数据被非法篡改 降低模块耦合度,内部修改不影响外部调用
继承
核心目标
代码复用与层次扩展
定义
子类复用父类的属性和方法,实现代码复用与层次化扩展。
解释
子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
多态
核心目标
接口统一与行为多样化
定义
同一个行为具有多个不同表现形式或形态的能力。
解释
表现形式为,子类重写父类方法,实现类实现接口方法,子类重写抽象类方法。
抽象
核心目标
定义规范与隐藏复杂度
定义
抽象就是忽略关注主题与当前目标无关的信息,以便更关注于与当前目标有关的信息。抽象并不打算了解全部问题,而只关注于主题相关性较大的部分,且暂时不用关注部分细节。
解释
抽象包括两个方面,一是过程抽象,二是数据抽象。过程抽象,关注于目标的功能是什么,而不是功能是怎么实现的。数据抽象,关注于提取目标的特性信息。
类与对象、构造方法
类
定义对象的蓝图,包括属性和方法。
对象
类的实例,具有状态和行为
方法
定义类的行为,包含在类中的函数
方法重载
同一个类中可以有多个同名的方法,但仅有参数不同
方法重写
只能由子类重写父类的方法,且方法的名字、参数、返回值类型不可变,权限范围不能小于父类
方法重写是Java多态的基石
接口 vs 抽象类
内部类(静态/成员/局部/匿名)
异常处理
异常体系(Throwable/Error/Exception)
throwable
error
通常是程序无法处理的错误,大多数与代码无关,由于它们在应用程序的控制和处理能力之外,因此它们是无法被捕获的,如:OutOfMemoryError/StackOverflowError
exception
RuntimeException
非受检异常,不强制使用Catch捕获
ArrayIndexOutOfBoundsException,数组越界异常 NullPointerException,空指针异常 IllegalArgumentException,非法参数异常 NegativeArraySizeException,数组长度为负异常 IllegalStateException,非法状态异常 ClassCastException,类型转换异常
CheckedException
受检异常,必须显示地通过Catch捕获,因为接收到该异常时,可以清晰的知道出问题的地方,调用者需要根据上下文来决定在异常时如何处理
NoSuchFieldException,表示该类没有指定名称抛出来的异常。 IllegalAccessException,不允许访问某个类的异常。 ClassNotFoundException,类没有找到抛出异常。 IOException, IO异常。 NumberFormatException,数值类型的格式错误
try-catch-finally、try-with-resources
资源关闭方式
catch:需要在finally中手动关闭
with:自动关闭,通过实现AutoCloseable接口实现
代码复杂度
catch:高,嵌套多,容易遗漏关闭
with:低,声明即管理
异常覆盖风险
catch:高,finally异常覆盖主异常
with:低,抑制异常机制保留主异常
使用版本
catch:所有Java版本
with:Java7+
资源声明位置
try外部
with:try括号内
集合框架
Collection体系:List(ArrayList/LinkedList)、Set(HashSet/TreeSet)
List
ArrayList:基于动态数组实现,支持随机访问,插入删除效率较低(尤其在中间位置),线程不安全,适用于读多写少场景
扩容机制:当添加元素时容量不足,自动扩容为原容量的1.5倍(原容量右移1位加上原容量)
扩容触发条件:在添加元素前检查容量,若当前元素个数大于等于数组长度,则触发扩容
缩容操作:ArrayList不提供自动缩容机制,但可通过trimToSize()手动将容量调整为当前实际元素数量
扩容过程:创建新数组(新容量大小),使用System.arraycopy将原数组数据复制到新数组,替换原数组引用
初始容量:默认初始容量为10,若在构造时指定初始容量,则以指定值为准
多次扩容影响:频繁添加元素可能导致多次扩容,影响性能,建议预先设置合理初始
LinkedList:基于双向链表实现,插入删除效率高,随机访问性能差,占用内存较多,适用于频繁增删操作的场景
Vector:线程安全的动态数组,内部方法多为同步方法,性能较低,已被ArrayList + Collections.synchronizedList替代
Stack:继承自Vector,实现栈结构(后进先出),提供push、pop、peek等操作,使用较少,推荐使用Deque替代
CopyOnWriteArrayList:写时复制的线程安全List,适用于读多写少的并发场景,写操作加锁并复制整个数组,读操作无锁
Set
Map体系:HashMap(源码+扩容)、ConcurrentHashMap、LinkedHashMap
HashMap
问题
1. 链表如何转换为红黑树?
1. 链表长度阈值 :当单个桶中的链表长度达到8时,该链表会被转换为红黑树。 2. 最小树化容量 :HashMap的总容量(桶数组大小)必须至少为64 。如果容量小于64,即使链表长度达到8,也不会进行树化,而是会选择扩容。
红黑树
基本特点
红黑树是一种自平衡的二叉查找树,它通过以下规则保持树的高度大致为 O(log n)
五条基本性质
1. 每个节点要么是红色,要么是黑色
2. 根节点是黑色
3. 所有叶子节点(NIL 节点)都是黑色
4. 如果一个节点是红色,那么它的两个子节点必须是黑色(即不能有两个连续的红色节点)
5. 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点
平衡调整的核心操作
1. 颜色反转
2. 左旋和右旋
3. 递归调整
ConcurrentHashMap
LinkedHashMap
迭代器(Iterator)、Fail-Fast机制
stream流
I/O
传统I/O
字节流/字符流(FileInputStream/BufferedReader)
NIO
NIO核心:Channel、Buffer、Selector
零拷贝、多路复用
AIO
Java高级
多线程与并发
线程创建(Thread/Runnable/Callable)
创建线程的几种方式
继承Thread类并重写run方法
实现Runnable接口并重写run方法
实现Callable接口并配合FutureTask使用
使用线程池(ExecutorService)提交任务
使用 Executors 工厂类创建线程池(如 newFixedThreadPool、newCachedThreadPool、newSingleThreadExecutor)
直接通过 ThreadPoolExecutor 构造函数自定义线程池(可精确控制核心线程数、最大线程数、队列类型、拒绝策略等)
使用 Spring 的 ThreadPoolTaskExecutor 在 Spring 环境下集成线程池(便于与容器管理结合)
利用 CompletableFuture 的 supplyAsync 或 runAsync 方法配合自定义线程池实现异步任务提交
通过 ScheduledExecutorService 创建支持定时和周期性任务的线程池(适用于延迟执行或周期调度场景)
线程池执行任务的流程
提交任务到线程池:通过 execute() 提交无返回值任务,或 submit() 提交有返回值任务(返回 Future 对象)
任务调度与执行:线程池根据核心线程数、最大线程数、工作队列等参数决定是创建新线程还是将任务放入队列
当核心线程数未满时,创建新线程处理任务,即使有空闲线程
当核心线程数已满且工作队列未满时,将任务放入队列等待执行
当工作队列已满且线程数小于最大线程数时,创建非核心线程处理任务
当线程数达到最大线程数且队列已满时,触发拒绝策略处理新任务
任务执行完成后,线程会从队列中持续获取新任务,实现复用
当非核心线程空闲时间超过线程池的keepAliveTime时,会被自动回收
在线程池执行shutdown或shutdownNow操作时,非核心线程将被关闭
如果工作队列为空且非核心线程处于空闲状态,超过存活时间后即触发关闭
动态调小线程池的maximumPoolSize时,超出新上限的非核心线程在空闲时会被终止
线程复用机制:线程池中的工作线程会循环从任务队列中获取任务并执行,实现线程的重复利用
任务拒绝策略触发:当线程池饱和且队列满时,根据配置的拒绝策略(如 AbortPolicy、CallerRunsPolicy 等)处理新任务
AbortPolicy:直接抛出 RejectedExecutionException 异常,阻止任务提交,适用于对系统稳定性要求高、不允许任务丢失的场景。
CallerRunsPolicy:由提交任务的线程自行执行该任务,起到减缓任务提交速度的作用,适用于调用者线程可承担执行任务压力的场景。
DiscardPolicy:静默丢弃无法处理的任务,不抛异常也不执行,适用于允许任务丢失且不希望阻塞系统的场景。
DiscardOldestPolicy:丢弃队列中等待最久的任务(即队首任务),然后尝试提交当前任务,适用于希望保留最新任务的场景
线程池关闭流程:调用 shutdown() 或 shutdownNow() 方法,停止接收新任务,并逐步释放线程资源
使用CompletableFuture的异步任务创建
使用 supplyAsync 启动有返回值的异步任务,可配合 Executor 自定义线程池
使用 runAsync 启动无返回值的异步任务,适用于不需要结果的异步执行
通过 thenApply、thenAccept、thenRun 实现任务的链式调用与结果处理
使用 thenCombine、thenCompose 实现多个异步任务的组合与依赖处理
利用 exceptionally 或 handle 方法进行异步任务的异常处理与降级
通过 join 或 get 方法获取异步执行结果,注意 join 不抛检査异常而 get 会
使用 allOf 和 anyOf 实现多个 CompletableFuture 的聚合控制
使用Spring的@Async注解方式
@Async注解的实现基于Spring的AOP代理机制,通过动态代理拦截标注了@Async的方法调用
方法被调用时,代理会将该方法的执行提交到配置的TaskExecutor线程池中,实现异步执行
需要启用@EnableAsync注解来开启异步功能,Spring才会扫描并处理@Async注解
默认情况下,Spring使用SimpleAsyncTaskExecutor或应用上下文中的TaskExecutor作为执行器
支持自定义线程池,可通过实现AsyncConfigurer接口或配置TaskExecutor Bean来指定异步执行的线程池
异步方法所在类必须被Spring容器管理,且方法不能是private、static或final,以确保代理生效
若在同一个类中调用@Async方法(内部调用),由于代理失效,会导致异步不生效,需通过自我注入等方式解决
返回值支持void和Future类型,使用CompletableFuture可实现更复杂的异步编排和结果获取
线程状态转换、上下文切换
主线程与子线程通信
同步机制:synchronized、Lock(ReentrantLock)
JUC工具包:线程池(ThreadPoolExecutor参数)
JUC工具包:并发集合(CopyOnWriteArrayList/BlockingQueue)
JUC工具包:原子类(AtomicInteger)、CAS原理
本质是乐观锁
并发工具:CountDownLatch、CyclicBarrier、Semaphore
JVM原理
内存模型:堆(新生代/老年代)、方法区、栈、程序计数器
1.7及以前
1.8以后
分区介绍
线程共享
堆
特征:线程共享
作用:保存对象实例,所有对象实例都要在堆上分配
配置参数:-Xmn、-Xms、-Xmx
异常:OOM java heap space
1.7
方法区
特征:线程共享
作用:存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据
配置参数:-XX:PermSize:16M、-XX:MaxPermSize:64M
异常:
1.7 OOM PermGen space
1.8 OOM Metaspace
运行时常量池
特征:方法区的一部分
作用:字面量及符号引用
配置参数:无
异常:无
线程私有
虚拟机栈
特征:线程私有,使用连续的内存空间
作用:java方法存储的内存模型,存储局部变量表、操作数栈、动态链接、方法出口等
配置参数:-Xss
异常:OOM,stackOverFlow
本地方法栈
特征:线程私有
作用:为虚拟机使用到的本地方法服务,方便与外界环境交互
配置参数:无
异常:OOM,stackOverFlow
程序计数器
特征:线程私有,占用内存小
作用:字节码行号指示器
配置参数:无
异常:无
本地内存
直接内存
1.8
元空间
运行时常量池
特征:元空间的一部分
作用:字面量及符号引用
配置参数:无
异常:无
垃圾回收:收集器(CMS、G1、ZGC)
Serial收集器:单线程执行垃圾回收,适用于客户端应用,简单高效,但回收期间会暂停所有用户线程(Stop-The-World)。
Parallel Scavenge收集器:关注吞吐量的新生代收集器,使用多线程并行回收,适合后台计算型应用,可与PS MarkSweep或PS Old代收集器配合使用。
CMS(Concurrent Mark Sweep)收集器:以获取最短回收停顿时间为目标的老年代收集器,采用并发标记清除算法,支持与用户线程并发执行,但存在CPU资源占用高、无法处理浮动垃圾和可能出现碎片化的问题。
G1(Garbage First)收集器:面向服务端的全区域收集器,将堆划分为多个Region,支持并行与并发模式,可预测停顿时间模型,优先回收垃圾最多的区域,避免碎片化,适用于大内存、低延迟场景。
ZGC(Z Garbage Collector)收集器:低延迟收集器,支持超大堆(TB级),停顿时间极短(通常小于10ms),基于着色指针和读屏障实现并发整理,适用于对响应时间敏感的大型应用。
Shenandoah收集器:与ZGC类似,强调低停顿时间,通过Brooks指针实现并发压缩,可在GC过程中移动对象而不显著影响应用线程,适合大堆和低延迟需求场景
性能监控:jstack/jmap/jstat、MAT分析内存泄漏
垃圾回收:GC调优参数(-Xms/-Xmx/-XX:SurvivorRatio)
垃圾回收:算法(标记清除/复制/标记整理)
类加载机制:双亲委派、自定义类加载器
JDK新特性
Java 8:Lambda表达式、Stream API、Optional、方法引用
Java 11:HTTP Client、局部变量类型推断(var)
Java 17:密封类(sealed class)、模式匹配
框架与中间件
框架
Spring框架
IOC容器:Bean生命周期、依赖注入
依赖注入
springboot如何处理循环依赖
1. 实例化 BeanA 后,将其工厂放入三级缓存; 2. 为 BeanA 注入 BeanB 时,发现 BeanB 未创建,转而实例化 BeanB; 3. BeanB 注入 BeanA 时,从三级缓存获取 BeanA 的半成品对象(提前暴露); 4. BeanB 完成初始化,BeanA 随后完成属性注入。
Setter/字段注入允许 Spring 在属性填充阶段注入半成品 Bean,而构造器注入需在实例化时获得完整依赖,故无法解决。
使用Autowired注解时,可添加Lazy注解延迟加载
Bean生命周期
Bean生命周期的本质
SpringBean生命周期是IOC容器管理Bean从创建到销毁的全过程
1. 解耦:将对象创建、依赖注入与业务逻辑分离
2. 控制反转:由容器掌握Bean的初始化流程
3. 可扩展性:通过扩展点干预Bean的创建过程
关键点:生命周期不是线性流程,而是由容器时间驱动的网状回调体系
完整声明周期流程图解(8大阶段)
分阶段深度解析
阶段一:实例化
触发机制:容器首次获取Bean时(Singleton)或每次请求时(Prototype)
底层机制:
通过BeanDefinition获取类元信息
使用InstantiationStrategy执行实例化(默认CglibSubclassingInstantiationStrategy)
// 源码片段:AbstractAutowireCapableBeanFactory.createBeanInstance() if (mbd.getFactoryMethodName() != null) { return instantiateUsingFactoryMethod(beanName, mbd, args); // 工厂方法创建 } return instantiateBean(beanName, mbd); // 构造器创建
特殊扩展:InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()可返回代理对象 短路 默认创建流程
返回代理对象后,默认创建流程被跳过,即:默认创建流程被短路了
阶段二:属性填充
依赖注入方式
字段注入(@Autowired)
构造器注入(@Autowired on constructor)
Setter注入(@Autowired on setter)
底层流程
解析AutowiredAnnotationBeanPostProcessor收集的注入点
按类型/名称查找依赖Bean
递归触发依赖Bean的创建
关键扩展点
InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation():可阻止属性注入
InstantiationAwareBeanPostProcessor.postProcessProperties():自定义属性值
阶段三:Aware接口回调
设计目的
让Bean感知容器环境
调用顺序
BeanNameAware → 设置Bean ID
BeanClassLoaderAware → 设置类加载器
BeanFactoryAware → 设置BeanFactory引用
EnvironmentAware → 设置环境变量
EmbeddedValueResolverAware → 设置值解析器
ResourceLoaderAware → 设置资源加载器(ApplicationContext场景)
ApplicationEventPublisherAware → 设置事件发布器
MessageSourceAware → 设置国际化资源
ApplicationContextAware → 设置ApplicationContext
易错点
ApplicationContextAware需在ApplicationContext环境下生效
阶段四:BeanPostProcessor前置处理(Pre-Initialization)
核心接口
BeanPostProcessor.postProcessBeforeInitialization()
典型应用
@PostConstruct注解处理(CommonAnnotationBeanPostProcessor)
为Bean生成代理(AOP在此阶段准备)
阶段五:初始化(Initialization)
InitializingBean.afterPropertiesSet()
接口方式:实现InitializingBean接口
执行时机:所有属性注入完成后
自定义init-method
XML配置:<bean init-method="customInit">
注解配置:@Bean(initMethod = "customInit")
@PostConstruct注解方法
执行顺序:最先执行(通过CommonAnnotationBeanPostProcessor驱动)
三种方式执行顺序
@PostConstruct → InitializingBean.afterPropertiesSet() → init-method
阶段六:BeanPostProcessor后置处理(Post-Initialization)
核心接口
BeanPostProcessor.postProcessAfterInitialization()
核心作用
AOP代理生成:AbstractAutoProxyCreator在此创建JDK/CGLIB代理
缓存Bean(如Spring Cache)
包装Bean(如TransactionInterceptor)
阶段七:使用期(In Use)
Bean状态
完全初始化的可用状态
特殊关注
原型Bean(Prototype)每次请求都走完整生命周期
单例Bean(Singleton)存在容器级缓存中
作用域扩展(Request/Session):通过Scope接口管理
阶段八:销毁(Destruction)
@PreDestroy注解方法(最先执行)
DisposableBean.destroy()(接口方式)
自定义destroy-method(XML/注解配置)
特殊扩展:DestructionAwareBeanPostProcessor.postProcessBeforeDestruction()
销毁触发条件
单例Bean:容器关闭时(ConfigurableApplicationContext.close())
原型Bean:容器不管理销毁,需手动调用或使用@Scope(proxyMode=...)
AOP:动态代理(JDK/CGLIB)、切面编程
Spring Boot
注解
@Configuration和@Component有什么差异
1. @Configuration是@Component的子类
2. @Configuration=配置类+CGLIB 代理机制,使用@Bean时是单例的
3. @Component=普通组件,无代理,误用@Bean会导致多例
并发请求容易导致多例,@Bean方法间调用一定会导致多例
导致多例的原因都是创建过程都未被Spring管理
核心启动注解
@SpringBootApplication
作用
主启动注解 组合了@Configuration+@EnableAutoConfiguration+@ComponentScan
关系说明
核心入口,触发自动配置和组件扫描
@EnableAutoConfiguration
作用
启用自动配置机制 通过spring.factories加载配置类
关系说明
被@SpringBootApplication包含,是自动配置的核心触发器
@ComponentScan
作用
扫描当前包及子包下的@Component、@Service等组件
关系说明
被@SpringBootApplication包含,与自动配置协同工作
配置管理注解
@Configuration
作用
声明配置类 内部包含@Bean方法定义Bean
关系说明
自动配置类(如DataSourceAutoConfiguration)的基础注解
@Bean
作用
在配置类中定义单例Bean 替代XML配置
关系说明
需配合@Configuration使用,自动配置的核心实现手段
@ConditionalOnClass
作用
条件装配 当类路径存在指定类时生效(如DataSource.class)
关系说明
控制自动配置类的激活,避免无效装配
@ConditionalOnMissingBean
作用
无自定义Bean时激活自动配置
关系说明
IOC中Bean是否存在,避免Bean冲突
@ConditionalOnClass
作用
根据配置属性条件装配
关系说明
外部配置文件中的属性值,基于配置动态启用功能,与Bean注册顺序无关
@ConfigurationProperties
作用
绑定配置文件属性 将application.properties的值注入Java对象
关系说明
与@EnableConfigurationProperties联用,覆盖自动配置默认值
依赖注入注解
@Autowired
作用
自动注入依赖 按类型匹配Bean
关系说明
常与@Component系列注解配合,解决Bean依赖
@Qualifier
作用
按名称指定注入的Bean 解决同一类型多个Bean的冲突
关系说明
需配合@Autowired使用,精确控制注入目标
@Primary
作用
标注优先注入的Bean 当存在多个同类型Bean时生效
关系说明
与@Bean或@Component联用,避免@Qualifier的硬编码
web开发注解
@RestController
作用
组合注解 =@Controller+@ResponseBody 直接返回JSON数据
关系说明
取代传统@Controller,简化RESTful开发
@RequestMapping
作用
定义请求映射路径,支持GET/POST等
关系说明
被@GetMapping/@PostMapping等细化注解继承
@PathVariable
作用
从URL路径获取参数,如/user/{id}
关系说明
需在@RequestMapping定义的路径中使用
@RequestParam
作用
从查询参数获取值,如?name=John
关系说明
与@PathVariable互补,处理不同参数来源
数据访问注解
@Entity
作用
声明JPA实体类,对应数据库表
关系说明
需配合@Id定义主键,被@Repository扫描
@Repository
作用
标记数据访问层组件,继承自@Component
关系说明
被@SpringBootApplication扫描,自动注入Service层
@Transactional
作用
声明事务边界,方法内数据库操作原子性执行
关系说明
作用于Service层方法,依赖DataSource自动配置
注解间关系
注解关系总结
启动层:@SpringBootApplication作为总控,协调自动配置(@EnableAutoConfiguration)、组件扫描(@ComponentScan)和配置类(@Configuration)。
自动配置层:通过条件注解(@ConditionalOnXxx)动态注册@Bean,优先级低于用户自定义Bean。
开发层:组件扫描加载@Component衍生注解(如@RestController),依赖注入(@Autowired)解决协助关系。
自动配置
核心机制
1. @EnableAutoConfiguration注解
在@SpringBootApplication注解中隐含了@EnableAutoConfiguration,它通过@Import(AutoConfigurationImportSelector.class)加载自动配置类
2. 扫描spring.factories文件
Spring Boot启动时扫描所有依赖jar包中的META-INF/spring.factories文件,读取org.springframework.boot.autoconfigure.EnableAutoConfiguration键下注册的配置类全限定类名。
3. 条件注解控制装配
自动配置类使用 @Conditional 系列注解(如 @ConditionalOnClass、@ConditionalOnMissingBean)动态判断是否生效: @ConditionalOnClass(DataSource.class):当类路径存在 DataSource 时生效 @ConditionalOnMissingBean:当容器中无指定 Bean 时生效
自动配置流程
1. 加载候选配置类
通过AutoConfigurationImportSelector从所有spring.factories中收集配置类
2. 过滤无效配置类
利用条件注解排除不满足条件的配置类(如缺少依赖类、容器中已存在自定义Bean)
3. 实例化并注册Bean
对筛选后的配置类进行解析,将其中的@Bean方法定义的组件注册到Spring容器
4. 应用外部配置
通过application.properties/application.yml中的属性覆盖自动配置的默认值
外部配置优先级(从高到低)
1. 命令行参数(--key=value)
2. jar包外部的config/application.properties
3. jar包内部的config/application.properties
4. jar包外部的application.properties
5. jar包内部的application.properties
6. @PropertySource注解指定的自定义配置
自定义扩展
1. 自定义Starter
创建META-INF/spring.factories并声明自动配置类
使用@Conditional控制条件装配
2. 禁用自动配置
添加排除的配置类@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
starter原理
Spring MVC:请求流程、拦截器
分布式与微服务
服务治理:Spring Cloud Netflix(Eureka/Ribbon/Hystrix)
配置中心:Nacos、Config
分布式事务:Seata、2PC/TCC
消息队列:Kafka(架构设计)、RocketMQ
数据库
关系型数据库
Jdbc
SQL优化:索引(B+树)、执行计划
事务管理
ACID
原子性(Atomicity):事务是最小的执行单位,不可分割,事务中的所有操作要么全部提交成功,要么全部失败回滚。
一致性(Consistency):事务执行前后,数据库从一个一致状态变换到另一个一致状态,不破坏数据完整性约束。
隔离性(Isolation):多个并发事务之间相互隔离,一个事务的执行不能干扰其他事务的执行。
持久性(Durability):事务一旦提交,其对数据库的修改就是永久性的,即使系统故障也不会
事务隔离级别
读未提交(Read Uncommitted):最低的隔离级别,允许一个事务读取另一个事务尚未提交的数据,可能导致脏读、不可重复读和幻读。
读已提交(Read Committed):一个事务只能读取其他事务已经提交的数据,避免了脏读,但无法解决不可重复读和幻读问题。
可重复读(Repeatable Read):确保在同一事务中多次读取同一数据时结果一致,避免了脏读和不可重复读,但在某些数据库中仍可能出现幻读(如MySQL InnoDB通过间隙锁解决)。
串行化(Serializable):最高的隔离级别,通过强制事务串行执行来避免脏读、不可重复读和幻读,但会显著降低并发性能
幻读/脏读
幻读:在一个事务中多次执行相同查询,由于其他事务插入或删除了满足条件的数据行,导致后续查询结果集出现新增或减少的“幻影”数据行。
脏读:一个事务读取到了另一个事务尚未提交的修改数据,若该数据随后被回滚,则读取到的数据是无效的,破坏了事务的隔离性。
不可重复读:在同一事务中多次读取同一数据项,由于其他事务在此期间修改并提交了该数据,导致前后读取结果不一致。
幻读与不可重复读的区别:不可重复读关注的是已有数据的修改(update),而幻读关注的是新增或删除数据导致结果集变化(insert/delete)。
解决幻读的机制:在可重复读隔离级别下,InnoDB通过间隙锁(Gap Lock)和临键锁(Next-Key Lock)锁定索引记录间的间隙,防止其他事务插入新记录,从而避免幻读。
使用 SELECT ... FOR UPDATE 在可重复读隔离级别下,对查询范围内的索引间隙自动添加间隙锁
通过唯一索引等值查询不存在的记录时,会自动在该位置添加间隙锁以防止幻读
在范围查询(如 WHERE id BETWEEN 10 AND 20)时配合 FOR UPDATE 或 LOCK IN SHARE MODE 添加间隙锁
利用临键锁(Next-Key Lock)机制,锁定记录本身及其前驱间隙,实现范围行锁与间隙锁的组合
确保事务隔离级别为 REPEATABLE READ,并在 WHERE 条件中使用索引字段才能触发间隙锁
隔离级别与并发问题对照关系:读未提交可能出现脏读、不可重复读、幻读;读已提交避免脏读;可重复读避免脏读和不可重复读(InnoDB下可避免幻读);串行化完全避免三者,但性能
事务传播机制
REQUIRED:支持当前事务,若不存在则新建事务
SUPPORTS:支持当前事务,若不存在则以非事务方式执行
MANDATORY:支持当前事务,若不存在则抛出异常
REQUIRES_NEW:新建事务,若当前存在事务则将其挂起
NOT_SUPPORTED:以非事务方式执行,若当前存在事务则将其挂起
NEVER:以非事务方式执行,若当前存在事务则抛出异常
NESTED:在当前事务内创建一个嵌套事务,外层事务回滚则内层也回滚,内层异常可独立回滚不影响外层
事务失效的几种场景
未正确声明事务方法:事务方法必须被 public 修饰,且不能被 static 或 final 修饰,否则 Spring 无法通过代理织入事务逻辑
自身调用问题:在同一个类中,非事务方法直接调用事务方法时,由于未经过代理对象,事务会失效
异常被捕获未抛出:事务默认只对未检查异常(RuntimeException 及其子类)回滚,若异常被 try-catch 捕获且未重新抛出,则事务不会回滚
事务传播配置不当:如使用了 `NOT_SUPPORTED` 或 `NEVER` 等传播级别,导致事务未按预期开启或被挂起
数据源未配置事务管理器:未正确配置 `PlatformTransactionManager` 或未启用 `@EnableTransactionManagement`,导致事务注解不生效
使用了不支持事务的数据库引擎:如 MySQL 使用 MyISAM 引擎,该引擎不支持事务,即使加了 @Transactional 也无效
代理失效场景:如通过 new 创建对象调用事务方法,绕过了 Spring 容器和代理机制,事务无法生效
连接池
HikariCP
Druid
ORM框架
Mybatis
Hibernate
分库分表:ShardingSphere
Mysql
显式使用行锁的 SQL 语法
通过 SELECT ... FOR UPDATE 或 SELECT ... LOCK IN SHARE MODE 显式加锁
FOR UPDATE是排他锁
IN SHARE MODE是共享锁
查询条件中没有索引时将升级为表锁
使用时建议使用SET innodb_lock_wait_timeout = 30; -- 超时时间(秒)设置超时时间,避免死锁
分页
limit offset, pageSize
注意深分页优化,使用pagehelper时也存在
可以手动实现_COUNT方法,直接查主表,避免嵌套查询
关闭参数自动分页,使用更高效的sql解析器
Oracle
分页
rownum
Pgsql
非关系型数据库
内存数据库
Redis
基础
为什么是单线程的
1. 避免上下文切换和锁竞争 :在多线程环境中,上下文切换和锁竞争可以成为性能瓶颈 。每当前后操作属于不同的线程时,就需要进行上下文切换,这会消耗大量的CPU资源。此外,线程之间的锁竞争也会导致效率降低。单线程模型避免了这些问题,因为所有操作都在同一个线程中顺序执行,无需加锁和解锁 。
2. 高效的数据处理 :Redis内部使用多种高效的数据结构,如哈希表、跳表和压缩列表等 。这些数据结构设计精良,能够在一个线程中快速执行复杂的操作,如列表添加或哈希表操作,而不需要担心多线程带来的同步问题 。
3. 非阻塞性和事件驱动的处理方式 :Redis使用事件驱动的非阻塞性IO处理方式。这意味着Redis可以有效地处理大量并发连接请求,而不会因为某些操作阻塞而影响整体性能。这种处理方式特别适合网络服务器和缓存系统,可以在单线程中处理数以万计的并发连接。
4. 简化实现和维护 :单线程模型简化了Redis的实现和维护。由于所有操作都在单一线程中执行,所以不需要考虑复杂的多线程同步和竞争问题,这不仅使得Redis的代码更加简洁,也减少了发生难以追踪的并发错误的可能性。
数据类型
基础数据类型
String
存储结构:二进制安全字符串
核心特性:可存储文本、数字、图片或序列化对象;支持自增/自减操作
典型应用场景:缓存、计数器、分布式锁
常用命令:SET/GET/INCR/DECR
HashMap
存储结构:键值对集合
核心特性:适合存储对象属性:支持字段级读写,避免全量操作
典型应用场景:用户信息、商品详情、配置项管理
常用命令:HSET/HGET/HGETALL
List
存储结构:双向链表
核心特性:有序元素集合;支持头部/尾部插入、阻塞弹出
典型应用场景:消息队列、最新动态、任务调度
常用命令:LPUSH/RPOP/LRANGE
Set
存储结构:哈希表实现的无序集合
核心特性:元素唯一;支持交/并/差集运算
典型应用场景:标签系统、共同好友、去重统计
常用命令:SADD/SINTER/SMEMBERS
Zset
存储结构:跳表+哈希表
核心特性:元素唯一且按分数排序;支持范围查询
典型应用场景:排行榜、延迟队列、带权重缓存
常用命令:ZADD/ZRANGE/ZREVRANK
高级数据类型
BitMap
基于String的位操作,节省空间
场景:用户签到、布隆过滤器
命令:SETBIT/GETBIT/BITCOUNT
HyperLogLog
概率算法,用于海量数据去重统计(误差率约0.81%)只存储不重复元素数量,不存储元素本身
场景:UV(独立访客)统计
命令:PFADD/PFCOUNT
GEO
存储经纬度,支持位置计算
场景:如附近的人
命令:GEOADD/GEODIST/GEORADIUS
Stream
消息队列(支持多消费者组、消息持久化)
命令:XADD/XREAD/XGROUP
持久化
备份
BGSAVE:后台在安装目录中创建dump.rdb文件
SAVE:在安装目录中创建dump.rdb文件
将dump.rdb移动到config get dir 获取到的目录,启动即可恢复
集群
布隆过滤器
过期策略
定期删除:Redis 每隔一段时间随机检查一批设置了过期时间的键,删除其中已过期的键,通过限制频率和耗时避免对 CPU 造成过大压力
惰性删除:只有在访问某个键时才检查其是否已过期,若过期则立即删除并返回 null,适用于过期键被频繁访问的场景
内存淘汰策略:当内存达到 maxmemory 限制时,结合过期键信息选择淘汰策略(如 volatile-lru、volatile-ttl 等),主动清理部分键释放
volatile-lru:从设置了过期时间的键中使用LRU(最近最少使用)算法淘汰键
volatile-ttl:从设置了过期时间的键中优先淘汰剩余生存时间(TTL)最短的键
volatile-random:从设置了过期时间的键中随机淘汰键
allkeys-lru:在所有键中使用LRU算法淘汰键,无论是否设置了过期时间
allkeys-random:在所有键中随机淘汰键
noeviction:不淘汰任何键,当内存不足时新写入操作将返回错误(默认策略
Memcached
文档数据库
MongoDB
CouchDB
CouchBase
ES
分散存储到节点,更容易产生小文件
存储时需要hash到指定的节点上
写入和查询之间存在延迟,写入完成后需要创建反转索引。每次写入完成后,需要重新打开indexReader刷新索引。最耗时的两个操作是build index和refresh index。build index时需要分词、计算权重等复杂操作;refresh index会重新打开index,这导致接收文档的速度不高。
列存储数据库
HBase
图形存储数据库
Neo4j
对象存储数据库
db4o
xml存储数据库
BaseX
中间件
keepalived
nginx
zookeeper
消息队列
rabbitMQ
rocketMQ
activeMQ
系统设计与性能优化
设计模式
创建型:单例(DCL/静态内部类)、工厂
行为型:观察者、策略、责任链
设计原则
单一职责原则
核心思想
一个类或者模块只应承担一种职责
作用
降低复杂度、提升可读性、减少修改引发的风险
示例
用户管理类不应同时处理登录验证和数据存储
开闭原则
核心思想
软件实体应对扩展开放,对修改关闭。
作用
通过继承、接口或组合扩展功能,避免修改原有代码。
示例
使用策略模式动态替换算法,而非修改已有类。
里氏替换原则
核心思想
子类必须能完全替代父类,且不影响程序正确性。
作用
确保继承关系的合理性,避免破坏父类契约。
示例
正方形不应继承长方形(因正方形修改边长会违反长方形的行为约束)。
依赖倒置原则
核心思想
高层模块不应依赖低层模块,二者都应依赖抽象(接口或抽象类)。
作用
解耦代码,提升灵活性。
示例
数据库操作依赖DataSource接口,而非具体的MySQLConnection类。
接口隔离原则
核心思想
客户端不应被迫依赖其不需要的接口方法。
作用
通过拆分臃肿接口,减少冗余实现。
示例
将Animal接口拆分为Flyable和Swimmable,避免鸟类实现游泳方法。
迪米特法则
核心思想
一个对象应尽可能少地与其他对象交互,降低耦合度。
作用
减少依赖链,提升模块独立性。
示例
通过中介类协调多个对象交互,而非直接跨层调用。
合成复用原则
核心思想
优先使用组合(has-a)而非继承(is-a)实现复用。
作用
避免继承带来的僵化性,灵活组合功能。
示例
汽车类包含Engine对象(组合),而非继承Engine类。
结构型:代理(动态代理)、适配器
jdkDynamicProxy
适用于接口代理,创建代理实例速度较快,适合代理接口的方法调用频率不高的场景。
cglib(字节码增强)
适用于没有接口的类代理,方法调用性能较高,适合方法调用频率较高的场景
高并发设计
限流:令牌桶/漏桶算法
降级熔断:Hystrix/Sentinel
分布式锁:Redis(Redisson)、ZooKeeper
负载均衡:Nginx、Ribbon
性能调优
JVM调优:堆大小、GC策略
SQL优化:慢查询分析、索引覆盖
缓存策略:缓存穿透/雪崩/击穿解决方案
异步化:CompletableFuture、消息队列解耦
大数据
Hadoop
组件
HDFS
分布式存储:将大文件分割成固定大小的块(默认 128MB 或 256MB),分散存储在多台服务器上。
高容错性:每块数据自动复制多份(默认 3 副本),即使部分节点故障,数据仍可恢复。
高吞吐量:适合顺序读写大文件,但不适合低延迟访问或频繁修改的场景。
MapReduce
并行处理:将任务拆分为 Map(数据映射)和 Reduce(结果汇总)两个阶段。
自动调度:框架负责分布式任务的调度、容错和负载均衡,开发者只需编写业务逻辑函数。
YARN
集群资源管理:负责分配计算资源(CPU、内存)给不同任务,支持多计算框架(如 Spark、Flink)运行在 Hadoop 上。
Hadoop Common
共享工具库与公共工具类
统一配置框架
安全认证与权限控制
RPC(远程过程调用)框架
本地库优化(Native Libraries)
核心优势
高扩展性:通过横向扩展(添加廉价节点)轻松提升存储和计算能力,支持 PB 级数据处理。
容错性:自动处理节点故障,数据备份和任务重试机制确保作业持续运行。
成本效益:利用普通硬件而非高端服务器,显著降低大规模数据处理的成本。
高可靠性:数据多副本存储与计算任务冗余执行,保障系统稳定性。
典型应用场景
海量日志分析(如用户行为追踪)
离线批处理(如数据清洗、报表生成)
机器学习数据预处理(大规模特征提取)
局限性与适用边界
不适用实时计算:设计侧重高吞吐而非低延迟,实时分析需结合 Spark/Flink 等框架。
小文件处理效率低:HDFS 更适合大文件存储,大量小文件会降低性能。
作业调度
Job对象执行步骤
客户端创建一个Job对象,并配置作业相关设置(如输入路径、输出路径、Mapper类、Reducer类等)
客户端调用Job的submit()方法,将作业提交给集群
客户端与ResourceManager通信,获取一个应用程序ID,并为该Job创建Application Master
Application Master 向ResourceManager请求资源,并根据资源的分配执行任务
任务运行过程中,任务输出、状态甚至失败都会被ApplicationMaster监控
ApplicationMaster完成所有任务后,通知ResourceManager作业完成
重点
客户端是作业提交的起点,准备作业配置,并与ResourceManager进行通信
ResourceManager负责整个集群的资源管理和分配,会为每个Job创建一个ApplicationMaster
ApplicationMaster是每个应用的管理者,负责与NodeManager通信,获取资源并运行任务。让客户端与ResourceManager之间的通信变得简单和有序
NodeManager负责为每个节点上的容器分配资源,并监控每个容器的运行状态,任务实际运行在容器中
容器是ResourceManager分配的资源单元,包含了CPU、内存等资源。Mapper和Reduce任务都在这些容器中运行。
调度策略
FIFO调度器
将应用按提交顺序排列成单一队列,严格遵循“先提交先执行”原则,只有前一个应用资源分配完毕后才处理下一个。
实现简单,ResourceManager 负载低。
资源垄断问题
不支持多队列
公平调度器
核心设计
多队列分层结构
集群资源划分为多个独立队列(如 queueA、queueB),每个队列分配固定容量(如 30% 资源)
队列内调度
队列内部默认使用 FIFO,支持优先级(可配置)
关键特性
弹性资源共享
若某队列资源空闲,可被其他队列临时借用,提高利用率
资源限制
队列内任务不能超额占用资源,避免单一应用影响整体稳定性
不支持抢占
一旦任务启动,资源不会被高优先级任务强占
适用场景
大型企业多部门共享集群(如 Yahoo 生产环境),需资源隔离和配额保障
容量调度器
核心目标
动态平衡资源分配,确保所有应用长期平均获得公平份额的资源
工作机制
多队列分组
支持用户/项目分组队列,每队列可配置最小资源保障(minResources)
权重调整
根据应用需求(如优先级、等待时间)动态分配资源
支持抢占
若新提交的高优先级任务资源不足,可回收低优先级任务的资源(需配置)
优势
提高小任务响应速度,避免大任务阻塞集群
适配动态负载变化,适合多类型作业混合场景
适用场景
云服务、多租户环境(如 Facebook),需快速响应交互式查询和实时任务
工具链与DevOps
开发工具
IDE:IntelliJ IDEA(调试技巧)
构建工具:Maven(依赖管理)、Gradle
运维部署
容器化:Docker镜像、Kubernetes
docker
常用命令
环境与版本管理
docker version
docker info
镜像管理
镜像拉取与搜索
docker pull nginx:latest
docker search redis
本地镜像操作
docker images
docker rmi nginx:latest
docker build -t myapp:v1 .
导入导出
docker save nginx > nginx.tar
docker load < nginx.tar
容器生命周期管理
docker run
docker start/stop/restart
docker exec
docker rm
docker ps
数据持久化与网络
数据卷
docker volume create mydata
docker run -v mydata:/app/data nginx
网络管理
docker network create mynet
docker network ls
日志与监控
docker logs mynginx
docker stats
docker inspect mynginx
docker file
基础结构指令
from
workdir
构建过程指令
copy
add
run
arg
安全与权限配置
user
healthcheck
运行时配置指令
env
expose
volume
entrypoint
cmd
多阶段构建
构建优化技巧
调试与维护
Kubernetes
持续集成:Jenkins流水线
监控:Prometheus + Grafana + filebeat(轻量级数据来源收集与转发)
elk
elasticsearch
logstash + filebeat
kibana