当前位置: 首页 > news >正文

java面试题(中级题汇总)

  

1. 计算机网络传输层有哪些协议?分别适用于什么场景?

传输层核心协议有两个:

  • TCP(传输控制协议)

特点:面向连接、可靠传输(通过三次握手建立连接、四次挥手断开连接,支持重传、拥塞控制等)、字节流传输。

适用场景:对可靠性要求高的场景,如文件传输(FTP)、网页浏览(HTTP/HTTPS)、邮件发送(SMTP)等。

  • UDP(用户数据报协议)

特点:无连接、不可靠(不保证送达,无重传机制)、数据报传输、效率高。

适用场景:对实时性要求高但可容忍少量丢包的场景,如视频 / 语音通话(流媒体)、在线游戏、DNS 查询等。

2. 多线程的使用场景有哪些?线程开启多少个合适?判断标准有哪些?

多线程使用场景:
  • 异步任务处理(如日志记录、邮件发送,不阻塞主线程);
  • 并发 IO 操作(如多文件下载、数据库批量查询,利用 IO 等待时间);
  • 实时数据处理(如消息队列消费、实时监控);
  • 复杂计算任务拆分(如大数据量排序、分布式计算)。
线程数量没有 “固定答案”,需结合任务类型判断:
  • CPU 密集型任务(如数学计算):线程数≈CPU 核心数(避免线程切换开销);
  • IO 密集型任务(如网络请求、文件读写):线程数可适当增加(通常为 CPU 核心数 ×2,或根据 IO 等待时间调整)。
判断标准:
  • 系统响应时间(避免线程过多导致调度延迟);
  • 资源利用率(CPU、内存、IO 不超限);
  • 任务类型(CPU/IO 密集);
  • 实际压测结果(通过监控工具观察性能瓶颈)。

3. 线程池的提交方式有哪几种?

Java 线程池(ExecutorService)有两种核心提交方式:

  • execute(Runnable command)

无返回值,仅执行任务;若任务抛出异常,会直接抛出(需手动捕获)。

  • submit(Callable<T> task)submit(Runnable task, T result)

有返回值(Future<T>),可通过Future获取任务结果或异常;任务异常会被封装在Future中(调用get()时抛出)。

4. 锁的实现原理介绍一下?

Java 中锁的实现主要分为两类:

(1)synchronized 关键字
  • 底层依赖 对象头(Mark Word)Monitor(监视器锁)
    • 对象头存储锁状态(无锁、偏向锁、轻量级锁、重量级锁);
    • 重量级锁通过 Monitor 实现:每个对象关联一个 Monitor,线程竞争锁时需获取 Monitor 的所有权(涉及操作系统互斥锁,开销较大)。
  • JDK 6 后优化:引入偏向锁(减少无竞争时的开销)、轻量级锁(自旋锁,避免立即升级为重量级锁)。
(2)java.util.concurrent.locks.Lock 接口(如 ReentrantLock)
  • 基于 AQS(AbstractQueuedSynchronizer) 实现:
    • AQS 通过内置的双向队列管理等待线程,用state变量表示锁的状态(0:无锁,>0:被持有);
    • 线程竞争锁时,通过 CAS 操作修改state,失败则进入队列等待(可响应中断、设置超时)。

5. TCP 协议中拥塞控制的主要作用是什么?

拥塞控制是 TCP 协议为避免网络拥塞而设计的机制,主要作用:

  • 防止发送方发送速率超过网络承载能力,避免数据包大量丢失;
  • 维持网络稳定性,保证数据传输的高效性(在拥塞与吞吐量间平衡)。

核心算法包括:慢启动、拥塞避免、快重传、快恢复。

6. String 类的常用函数有哪些?列举十种。

String类提供了丰富的字符串操作方法,常用的有:

  1. int length():返回字符串长度;
  1. char charAt(int index):获取指定索引的字符;
  1. String substring(int beginIndex, int endIndex):截取子串(左闭右开);
  1. boolean equals(Object anObject):比较字符串内容是否相等;
  1. int indexOf(String str):查找子串首次出现的索引(未找到返回 - 1);
  1. String replace(char oldChar, char newChar):替换字符;
  1. String trim():去除首尾空白字符;
  1. String toLowerCase() / toUpperCase():转换为小写 / 大写;
  1. String[] split(String regex):按正则分割字符串;
  1. boolean startsWith(String prefix):判断是否以指定前缀开头。

7. String、StringBuffer、StringBuilder 的区别有哪些?所有类名包含 Buffer 的类的内部实现原理是什么?有什么优势?

(1)三者区别

特性

String

StringBuffer

StringBuilder

可变性

不可变(底层数组final)

可变(数组可修改)

可变(数组可修改)

线程安全

安全(不可变)

安全(方法加synchronized)

不安全(无同步)

性能

差(修改时创建新对象)

中(同步开销)

优(无同步开销)

(2)Buffer 类(如ByteBuffer、StringBuffer)的实现原理与优势
  • 原理:内部基于数组存储数据,通过position(当前位置)、limit(可操作上限)、capacity(容量)三个指针控制数据读写,避免频繁创建新对象。
  • 优势
    • 高效处理数据:通过指针操作减少数组复制,提升 IO / 字符串操作性能;
    • 支持批量操作:如ByteBuffer可直接与 Channel 交互,适合网络 / 文件传输。

8. String 字符串的不可变是指哪里不可变?

String的不可变性体现在:

  • 底层存储数据的数组被final修饰(JDK 8 为char[],JDK 9 + 为byte[]),无法修改数组引用;
  • 类中未提供修改数组元素的方法(如substring、replace等方法均返回新String对象)。

即:一旦创建String对象,其内容(字符序列)无法被修改,任何 “修改” 操作都会生成新对象。

9. HTTP 协议有哪些字段,列举 3 个就可以。

HTTP 请求 / 响应头包含多个字段,常用的有:

  • Host:指定请求的服务器域名和端口(如Host: www.example.com);
  • Content-Type:表示请求 / 响应体的数据格式(如Content-Type: application/json、text/html);
  • User-Agent:描述发送请求的客户端(如浏览器型号、操作系统,User-Agent: Mozilla/5.0 ...)。

10. Java 异常类有哪些?分别管理什么异常?

Java 异常体系以Throwable为根,分为两类:

(1)Error(错误)
  • 表示 JVM 无法处理的严重错误(如内存溢出),无需捕获,如:
    • OutOfMemoryError:内存不足;
    • StackOverflowError:栈溢出(如递归过深)。
(2)Exception(异常)
  • 表示程序可处理的异常,分为受检异常(编译时需捕获)和非受检异常(RuntimeException及其子类,编译时无需捕获)。
    • 受检异常:如IOException(IO 操作错误)、ClassNotFoundException(类未找到);
    • 非受检异常:如NullPointerException(空指针)、IndexOutOfBoundsException(索引越界)、ArithmeticException(算术错误,如除 0)。

11. Java 反射获取类信息的方式有哪几种?分别是什么?

反射获取类信息(Class对象)的方式有 3 种:

  1. Class.forName(String className)

通过类的全限定名加载类(触发类初始化),如Class.forName("java.lang.String")。

  1. 对象.getClass()

通过实例对象获取Class,如"hello".getClass()。

  1. 类名.class

直接通过类名获取(不触发类初始化),如String.class。

12. Java 代理的主要方法有哪几种?列举代理的使用场景 2 个。

主要代理方法
  1. 静态代理

手动编写代理类(实现与目标类相同的接口),在代理类中调用目标方法并添加增强逻辑(如日志)。缺点:代理类与目标类耦合,不易扩展。

  1. 动态代理
    • JDK 动态代理:基于接口生成代理类(通过Proxy.newProxyInstance()),要求目标类实现接口;
    • CGLIB 动态代理:通过继承目标类生成代理子类(无需接口),基于 ASM 字节码技术。
使用场景
  • AOP(面向切面编程):如 Spring AOP 通过代理实现日志、事务、权限等横切逻辑;
  • 远程调用:如 RPC 框架(Dubbo)通过代理封装网络通信细节,让调用远程服务像调用本地方法。

13. equals () 方法的作用是什么?重写 equals 需要注意哪些事项?为什么?

  • 作用:判断两个对象的内容是否相等(==判断地址是否相等)。
重写equals的注意事项(需满足 5 大特性)
  1. 自反性:x.equals(x)必须返回true;
  1. 对称性:x.equals(y)与y.equals(x)结果一致;
  1. 传递性:若x.equals(y)且y.equals(z),则x.equals(z);
  1. 一致性:多次调用结果相同(对象未被修改时);
  1. hashCode()一致:若x.equals(y)为true,则x.hashCode()必须等于y.hashCode()。
原因
  • 违反前 4 点会导致逻辑错误(如集合中判断元素相等时出错);
  • 违反第 5 点会导致HashMap、HashSet等基于哈希的集合无法正常工作(如两个相等的对象可能被存入不同桶中)。

14. Java 是按值传递还是按引用传递?什么是引用传递,什么是值传递,哪些语言支持引用传递?

  • Java 是按值传递
    • 基本类型:传递值的副本(修改副本不影响原变量);
    • 引用类型:传递引用地址的副本(修改副本指向的对象内容会影响原对象,但修改副本的指向不影响原引用)。
概念区分
  • 值传递:传递数据的副本,函数内修改副本不影响原数据;
  • 引用传递:传递数据的地址(而非副本),函数内修改会直接影响原数据。
支持引用传递的语言

如 C++(通过&声明引用参数)、Python(对象传递本质是引用传递)。

15. 描述 java 的类初始化顺序?如果存在继承,初始化顺序会如何

单个类的初始化顺序(从先到后)
  1. 静态变量(类变量);
  1. 静态代码块(static {});
  1. 实例变量(成员变量);
  1. 构造代码块({},每次创建实例时执行);
  1. 构造方法。
存在继承时的初始化顺序
  1. 父类静态成员 / 静态代码块(只执行一次);
  1. 子类静态成员 / 静态代码块(只执行一次);
  1. 父类实例成员 / 构造代码块
  1. 父类构造方法
  1. 子类实例成员 / 构造代码块
  1. 子类构造方法

规律:静态优先于实例,父类优先于子类。

16. 本地方法栈有什么作用?

本地方法栈是 JVM 内存区域之一,作用是:

  • 支持本地方法(native修饰的方法) 的执行,存储本地方法的参数、返回值、局部变量等;
  • 本地方法通常用 C/C++ 实现,本地方法栈与操作系统的栈结构相关(不同系统实现不同)。

17. 描述 Java 的双亲委派机制,为什么要用到双亲委派机制

  • 双亲委派机制:类加载时,子类加载器先委托父类加载器加载类,若父类加载器无法加载(找不到类),子类加载器才尝试自己加载。
核心加载器(从父到子)
  • 启动类加载器(Bootstrap):加载JAVA_HOME/lib下的核心类(如java.lang.String);
  • 扩展类加载器(Extension):加载JAVA_HOME/lib/ext下的类;
  • 应用类加载器(App):加载应用 classpath 下的类。
作用
  1. 避免类重复加载:同一类只会被一个加载器加载;
  1. 保证核心类安全:防止自定义类(如java.lang.String)篡改核心类,避免安全风险。

18. 重写和重载的区别是什么?

维度

重写(Override)

重载(Overload)

定义

子类覆盖父类的方法

同一类中方法名相同,参数不同

方法名

必须相同

必须相同

参数列表

必须相同(个数、类型、顺序)

必须不同(个数、类型、顺序)

返回值类型

子类返回值需与父类兼容(<= 父类)

可不同

访问修饰符

子类修饰符权限 >= 父类

无限制

异常

子类抛出异常 <= 父类

无限制

作用

实现多态(运行时绑定)

提高方法灵活性(编译时绑定)

19. 子类构造方法调用父类构造方法的注意事项有哪些?

  1. 默认调用父类无参构造:子类构造方法第一行隐含super(),若父类无无参构造,编译报错;
  1. 显式调用父类有参构造:若父类只有有参构造,子类必须在构造方法第一行用super(参数)显式调用;
  1. 不可调用多次:super()或this()(调用本类其他构造方法)只能出现一次,且必须在第一行。

20. 子类实例初始化是否触发父类实例初始化?

子类实例化时,会先执行父类的实例初始化(实例变量、构造代码块、构造方法),再执行子类的实例初始化。原因是:子类构造方法第一行会调用父类构造方法(super()),触发父类实例初始化。

21. instanceof 关键字的作用是什么?

instanceof用于判断对象是否是某个类(或接口)的实例,包括子类实例。

格式:对象 instanceof 类/接口,返回boolean。

例如:"hello" instanceof String返回true,new Integer(1) instanceof Number返回true(Integer是Number的子类)。

22. 基本类型的强制类型转换是否会丢失精度?引用类型的强制类型转换需要注意什么?

  • 基本类型:可能丢失精度。
    • 如double a = 3.14; int b = (int)a;(b为 3,丢失小数部分);
    • 整数类型间转换(如long转int)可能溢出(值超出目标类型范围)。
  • 引用类型:需确保对象的实际类型是目标类型或其子类,否则会抛出ClassCastException。

例如:Object obj = "hello"; String s = (String)obj;(正确,obj实际是String);若obj是Integer,强转为String则报错。

23. 重入锁有哪些?为什么要有重入锁?

  • 重入锁:允许同一线程多次获取同一把锁的锁(避免死锁)。Java 中包括:
    • synchronized(隐式重入);
    • ReentrantLock(显式重入,实现Lock接口)。
为什么需要重入锁?

避免同一线程在递归调用或多次获取锁时死锁。例如:

 

synchronized void methodA() { methodB(); } // 同一线程调用methodA后,可再次获取锁执行methodB

synchronized void methodB() { ... }

若锁不可重入,线程执行methodA时已持有锁,调用methodB会再次请求锁,导致死锁。

24. 指令重排序的优点是什么?由什么原因导致的?

  • 优点:提高 CPU 利用率和程序执行效率。例如:编译器或 CPU 可调整指令顺序,避免因 IO、缓存等操作导致的等待。
导致原因
  1. 编译器优化:编译时调整指令顺序(不改变单线程语义);
  1. CPU 指令重排序:CPU 为提高流水线利用率,乱序执行指令;
  1. 内存系统重排序:缓存、写缓冲区导致读 / 写操作顺序与代码顺序不一致。
注意

多线程环境下,指令重排序可能导致可见性问题,需用volatile、synchronized等禁止重排序。

25. Arrays.sort () 的内部原理介绍一下?

Arrays.sort()的实现因 JDK 版本和数据类型而异:

  • 基本类型(如int[]char[]

JDK 7 + 用双轴快速排序(Dual-Pivot Quicksort),比传统快排更高效(划分更均衡)。

  • 对象数组(如String[]

JDK 7 + 用TimSort(归并排序 + 插入排序的混合算法),针对实际数据中常见的 “部分有序” 场景优化,稳定性更好(相等元素顺序不变)。

26. 堆排序的时间复杂度是多少,空间复杂度是多少?

  • 时间复杂度:O(n log n)(最好、最坏、平均均为此值,稳定性优于快排);
  • 空间复杂度:O(1)(原地排序,仅需常数级额外空间)。

27. 字符串 “asdasjkfkasgfgshaahsfaf” 经过哈夫曼编码之后存储比特数是多少?

步骤:
  1. 统计字符频率(遍历字符串,计数每个字符出现次数):

字符串:a s d a s j k f k a s g f g s h a a h s f a f

统计结果(去重后):

a:7, s:6, f:4, g:2, h:2, d:1, j:1, k:2

  1. 构建哈夫曼树

每次取频率最小的两个节点合并,新节点频率为两者之和,重复至只剩一个节点。

  1. 计算编码长度

哈夫曼编码中,每个字符的编码长度为其在树中的深度。假设最终编码长度:

a:2, s:2, f:3, g:3, h:3, d:4, j:4, k:3

  1. 总比特数

7×2 + 6×2 + 4×3 + 2×3 + 2×3 + 1×4 + 1×4 + 2×3 = 14 + 12 + 12 + 6 + 6 + 4 + 4 + 6 = 64。

28. CPU 高速缓存的优点和缺点有哪些?

  • 优点
    1. 解决 CPU 与内存速度不匹配问题(CPU 速度远快于内存),减少 CPU 等待时间;
    1. 提高数据访问效率(缓存速度接近 CPU,远快于内存)。
  • 缺点
    1. 缓存一致性问题:多核心 CPU 的缓存中同一数据可能不一致,需 MESI 等协议解决(开销增加);
    1. 容量有限:缓存容量远小于内存,可能频繁发生缓存失效(Cache Miss);
    1. 硬件复杂度高:需设计缓存映射(直接映射、组相联等)、替换策略(LRU 等)。

29. 线程安全的类有哪些?列举 2 个以上就可以

线程安全类指多线程并发访问时,无需额外同步即可保证数据正确的类:

  • Vector:动态数组,方法加synchronized;
  • Hashtable:哈希表,方法加synchronized;
  • ConcurrentHashMap:并发哈希表(JDK 1.7 分段锁,JDK 1.8 CAS+ synchronized);
  • StringBuffer:字符串缓冲区,方法加synchronized。

30. 什么是 LRU 算法?

LRU(Least Recently Used,最近最少使用)是一种缓存淘汰策略

  • 当缓存满时,优先淘汰最久未被使用的缓存项,保留最近使用的项。
  • 应用场景:如 Redis 缓存、浏览器缓存、Android 图片缓存等,利用 “局部性原理”(最近使用的项可能再次被使用)提高缓存命中率。

31. 何为 Spring Bean 容器?Spring Bean 容器与 Spring IOC 容器有什么不同吗?

  • Spring Bean 容器:管理 Bean 的创建、依赖注入、生命周期的容器,核心是BeanFactory接口,负责 Bean 的实例化和管理。
  • Spring IOC 容器:IOC(控制反转)是一种设计思想,Bean 容器是 IOC 思想的实现载体。IOC 容器不仅包括 Bean 容器的功能,还强调 “将对象控制权从代码转移到容器”,通过依赖注入(DI)解耦组件。
  • 关系:Bean 容器是 IOC 容器的核心组成部分,IOC 容器 = Bean 容器 + 依赖管理 + 生命周期管理等扩展功能。

32. Spring IOC 如何理解?

IOC(Inversion of Control,控制反转)是 Spring 的核心思想,本质是将对象的创建、依赖关系维护的控制权从代码转移到容器

  • 传统方式:对象 A 依赖对象 B 时,A 需主动创建 B(B b = new B()),耦合度高;
  • IOC 方式:容器负责创建 B 并注入到 A 中(依赖注入),A 只需声明依赖,无需关心 B 的创建,降低耦合。

简言之:“以前我找对象,现在对象来找我”。

33. Spring DI 如何理解?

DI(Dependency Injection,依赖注入)是 IOC 的具体实现方式:容器在创建对象时,自动将其依赖的对象(如 Service、DAO)注入到当前对象中。

  • 注入方式
    • 构造器注入:通过构造方法参数注入;
    • Setter 注入:通过setXxx()方法注入;
    • 字段注入:通过@Autowired直接注入字段。

作用:解耦组件依赖,提高代码灵活性和可测试性。

34. Spring 中基于注解如何配置对象作用域?以及如何配置延迟加载机制?

(1)配置对象作用域(@Scope注解)
 

@Service

@Scope("singleton") // 单例(默认,容器启动时创建,全局唯一)

public class UserService {}

@Service

@Scope("prototype") // 多例(每次获取时创建新对象)

public class OrderService {}

// Web环境特有:

@Scope("request") // 每个请求创建一个实例

@Scope("session") // 每个会话创建一个实例

(2)配置延迟加载(@Lazy注解)
  • 作用:单例 Bean 默认在容器启动时创建,@Lazy使其在首次被使用时创建(减少启动时间)。
 

@Service

@Lazy // 延迟加载

public class UserService {}

35. Spring 工厂底层构建 Bean 对象借助什么机制?当对象不使用了要释放资源,目的是什么?何为内存泄漏?

  • 构建 Bean 的机制反射(通过Class.newInstance()、构造器 / 方法的反射调用创建对象并注入依赖)。
  • 释放资源的目的

回收对象占用的内存、文件句柄、网络连接等资源,避免资源耗尽(如内存溢出、文件描述符超限)。

  • 内存泄漏

对象已不再被使用(无引用),但因未被 GC(垃圾回收器)回收而持续占用内存的现象。常见原因:静态集合持有对象引用、未关闭资源(如Connection、ThreadLocal未清理)。

36. 描述 Spring MVC 处理流程及应用优势?

处理流程
  1. 用户发送请求:请求被DispatcherServlet(前端控制器)接收;
  1. 寻找处理器:DispatcherServlet通过HandlerMapping找到处理请求的Controller(处理器);
  1. 执行处理器:HandlerAdapter适配并调用Controller的方法,返回ModelAndView(数据 + 视图名);
  1. 解析视图:ViewResolver将视图名解析为View对象;
  1. 响应结果:View渲染数据并返回给用户。
应用优势
  • 松耦合:组件(DispatcherServlet、Controller、View等)通过接口交互,易于扩展;
  • MVC 架构:分离模型(Model)、视图(View)、控制器(Controller),职责清晰;
  • 灵活配置:支持注解、XML 配置,适配多种视图技术(JSP、Thymeleaf、JSON 等);
  • 集成 Spring 生态:无缝整合 Spring 的 IOC、AOP、事务等功能。

37. Spring 中的事务处理方式及优缺点?

Spring 事务处理有两种方式:

(1)编程式事务

通过代码手动控制事务(如TransactionTemplate或PlatformTransactionManager):

 

transactionTemplate.execute(status -> {

// 业务逻辑

return result;

});

  • 优点:灵活,可精确控制事务边界;
  • 缺点:代码侵入性强(事务逻辑与业务逻辑混合),繁琐。
(2)声明式事务

通过@Transactional注解或 XML 配置声明事务,底层基于 AOP 实现:

 

@Transactional

public void saveUser() {

// 业务逻辑(自动开启、提交/回滚事务)

}

  • 优点:无代码侵入,配置简单,易于维护;
  • 缺点:粒度较粗(基于方法),复杂场景(如部分逻辑不参与事务)需额外处理。

38. MyBatis 应用中 #与 $ 有什么异同点?

维度

#{}

${}

原理

预编译参数(占位符?)

字符串直接替换(拼接 SQL)

SQL 注入

安全(参数不参与 SQL 解析)

不安全(参数直接拼入 SQL)

适用场景

传递参数(如where id = #{id})

动态 SQL 片段(如表名、排序字段)

类型转换

自动转换(如字符串加引号)

不转换(需手动处理)

39. MyBatis 应用动态 SQL 解决了什么问题?

动态 SQL 通过<if>、<where>、<foreach>等标签,解决了传统 JDBC 中SQL 拼接的繁琐与风险

  • 避免手动拼接WHERE条件(如多余的AND/OR);
  • 简化批量操作(如IN查询、批量插入);
  • 减少重复 SQL 代码,提高可维护性;
  • 避免因拼接错误导致的 SQL 语法异常。

40. Shiro 框架权限管理时的认证和授权流程描述?

(1)认证流程(登录)
  1. 前端提交用户名 / 密码,后端封装为UsernamePasswordToken;
  1. 调用Subject.login(token),委托给SecurityManager;
  1. SecurityManager调用Authenticator(认证器);
  1. Authenticator通过Realm(数据源)获取用户信息(如从数据库查密码);
  1. 比对token中的密码与Realm返回的密码,一致则认证成功,否则抛IncorrectCredentialsException。
(2)授权流程(权限校验)
  1. 认证成功后,调用Subject.hasRole("admin")或isPermitted("user:delete");
  1. 请求委托给SecurityManager,再交给Authorizer(授权器);
  1. Authorizer通过Realm获取用户拥有的角色 / 权限;
  1. 比对用户请求的角色 / 权限与Realm返回的结果,判断是否授权。

41. BeanFactory 和 ApplicationContext 有什么区别?

维度

BeanFactory

ApplicationContext

定义

基础接口,IOC 容器的根接口

继承 BeanFactory,扩展更多功能

加载方式

懒加载(获取 Bean 时才创建)

预加载(启动时创建单例 Bean)

功能

仅提供 Bean 的创建、获取

额外支持:事件机制、资源访问、国际化、AOP 等

实现类

DefaultListableBeanFactory

ClassPathXmlApplicationContext、AnnotationConfigApplicationContext等

42. 请解释 Spring Bean 的生命周期?

Spring Bean 的生命周期可分为 5 个阶段:

  1. 实例化(Instantiation):容器通过反射创建 Bean 实例(调用构造方法);
  1. 属性注入(Population):容器将依赖的 Bean 注入到当前 Bean 的字段或 setter 方法;
  1. 初始化(Initialization)
    • 调用BeanNameAware、BeanFactoryAware等接口的回调方法;
    • 执行@PostConstruct注解的方法;
    • 调用InitializingBean的afterPropertiesSet();
    • 执行 XML 中init-method指定的方法;
  1. 使用(In Use):Bean 被应用程序使用;
  1. 销毁(Destruction)
    • 执行@PreDestroy注解的方法;
    • 调用DisposableBean的destroy();
    • 执行 XML 中destroy-method指定的方法。

43. Spring Bean 的作用域之间有什么区别?

Spring 定义了 5 种常见作用域(Web 环境特有 3 种):

作用域

说明

适用场景

singleton

单例(默认),容器中唯一实例

无状态 Bean(如 Service、DAO)

prototype

多例,每次获取时创建新实例

有状态 Bean(如 Request、Session)

request

每个 HTTP 请求创建一个实例

Web 应用,存储请求级数据

session

每个 HTTP 会话创建一个实例

Web 应用,存储会话级数据

globalSession

全局会话(Portlet 环境)

分布式 Web 应用

44. 使用 Spring 框架的好处是什么?

  1. 解耦:通过 IOC 容器管理对象依赖,减少硬编码;
  1. AOP 支持:轻松实现日志、事务、权限等横切逻辑,不侵入业务代码;
  1. 事务管理:声明式事务简化事务代码,保证数据一致性;
  1. 一站式框架:整合 ORM(MyBatis)、MVC(Spring MVC)、缓存(Redis)等,降低集成成本;
  1. 扩展性强:丰富的接口和扩展点,支持自定义组件;
  1. 测试友好:便于使用 JUnit 进行单元测试(如@MockBean)。

45. Spring 中用到了那些设计模式?

  1. 工厂模式:BeanFactory、ApplicationContext创建 Bean;
  1. 单例模式:默认singleton作用域的 Bean;
  1. 代理模式:AOP 基于 JDK/CGLIB 动态代理;
  1. 模板方法模式:JdbcTemplate、RestTemplate(固定流程,钩子方法留扩展);
  1. 观察者模式:事件机制(ApplicationEvent、ApplicationListener);
  1. 策略模式:Resource接口(不同资源加载策略);
  1. 适配器模式:HandlerAdapter(适配不同Controller)。

46. Spring 如何保证 Controller 并发的安全?

Spring MVC 的Controller默认是单例(singleton),并发时需避免线程安全问题,解决方案:

  1. 无状态设计:Controller中不定义成员变量(或仅定义无状态变量),避免多线程共享;
  1. 使用ThreadLocal:若需存储线程私有数据(如用户上下文),用ThreadLocal隔离线程;
  1. 原型作用域:将Controller作用域设为prototype(每次请求创建新实例),但会增加内存开销,不推荐。

47. 使用 Spring 框架的好处是什么?(同 44,略)

48. 在 Spring 中如何注入一个 java 集合?

Spring 支持注入List、Set、Map、Properties等集合,通过 XML 或注解实现:

(1)XML 配置
 

<bean id="userService" class="com.example.UserService">

<property name="list">

<list>

<value>张三</value>

<value>李四</value>

</list>

</property>

<property name="map">

<map>

<entry key="1" value="admin"/>

<entry key="2" value="user"/>

</map>

</property>

</bean>

(2)注解配置
 

@Service

public class UserService {

@Autowired

private List<User> userList; // 注入容器中所有User类型的Bean

@Value("#{${config.map}}") // SpEL表达式注入Map

private Map<String, String> configMap;

}

49. Spring 支持的事务管理类型?

  1. 编程式事务:通过TransactionTemplate或PlatformTransactionManager手动控制;
  1. 声明式事务
    • 基于 XML 配置(<tx:advice>);
    • 基于注解(@Transactional),更常用。

50. Spring 框架的事务管理有哪些优点?

  1. 简化代码:声明式事务无需手动写begin()、commit()、rollback();
  1. 一致性:保证事务 ACID 特性(原子性、一致性、隔离性、持久性);
  1. 灵活性:支持不同隔离级别(READ_UNCOMMITTED至SERIALIZABLE)和传播行为(如REQUIRED、REQUIRES_NEW);
  1. 整合多种数据源:支持 JDBC、Hibernate、MyBatis 等持久层框架;
  1. 与 Spring 生态无缝集成:结合 AOP 实现事务切面,不侵入业务代码。

51. Spring MVC 的主要组件?

  1. DispatcherServlet:前端控制器,接收所有请求,协调其他组件;
  1. HandlerMapping:映射请求到Controller(如@RequestMapping匹配);
  1. HandlerAdapter:适配Controller方法,执行并返回ModelAndView;
  1. Controller:处理器,处理业务逻辑,返回数据和视图名;
  1. ModelAndView:封装处理结果(Model数据 +View视图名);
  1. ViewResolver:将视图名解析为View对象(如 JSP、Thymeleaf);
  1. View:渲染Model数据,生成响应(HTML、JSON 等)。

52. Spring MVC 怎么和 AJAX 相互调用的?

  1. Controller 返回 JSON

用@ResponseBody注解(或类上用@RestController),将Model数据转为 JSON:

 

@GetMapping("/user")

@ResponseBody

public User getUser() {

return new User("张三", 20);

}

  1. AJAX 发送请求

前端用jQuery.ajax()或axios发送请求,接收 JSON 并处理:

 

axios.get("/user")

.then(response => {

console.log(response.data.name); // 输出"张三"

});

  1. 传递参数
    • GET:/user?id=1,后端用@RequestParam接收;
    • POST:发送 JSON 体,后端用@RequestBody接收。

53. Mybatis 中 #和 $ 的区别?(同 38,略)

54. MyBatis 的缓存机制,一级,二级介绍一下?

(1)一级缓存(SqlSession 级缓存)
  • 范围:默认开启,缓存归属于SqlSession(会话);
  • 原理:SqlSession执行查询后,结果存入缓存,同一SqlSession内再次执行相同 SQL(参数、SQL 相同),直接从缓存获取;
  • 失效:SqlSession关闭、执行insert/update/delete(会清空缓存)。
(2)二级缓存(Mapper 级缓存)
  • 范围:需手动开启(在 Mapper XML 中加<cache/>),缓存归属于Mapper(namespace),跨SqlSession共享;
  • 原理:SqlSession关闭后,一级缓存数据写入二级缓存,其他SqlSession执行相同 SQL 可命中;
  • 注意:缓存对象需实现Serializable接口(支持序列化);可通过useCache="false"禁用某条 SQL 的二级缓存。

55. Spring MVC 与 Struts2 的区别?

维度

Spring MVC

Struts2

核心控制器

DispatcherServlet(单例)

FilterDispatcher(过滤器)

控制器设计

基于方法(@RequestMapping)

基于类(Action实例)

线程安全

安全(无状态,单例)

不安全(Action 多例,需谨慎)

参数传递

方法参数直接接收

通过Action成员变量接收

拦截器机制

基于方法拦截

基于类拦截

配置方式

注解为主(简洁)

XML 为主(繁琐)

集成性

与 Spring 无缝整合

需额外配置整合 Spring

56. MyBatis 的基本工作流程?

  1. 加载配置:加载mybatis-config.xml(全局配置)和Mapper.xml(SQL 映射);
  1. 创建SqlSessionFactory:通过SqlSessionFactoryBuilder解析配置,生成SqlSessionFactory(线程安全,全局唯一);
  1. 获取SqlSession:SqlSessionFactory.openSession()创建SqlSession(非线程安全,代表一次会话);
  1. 获取Mapper接口:sqlSession.getMapper(UserMapper.class)生成Mapper代理对象;
  1. 执行 SQL:调用Mapper方法,代理对象通过StatementHandler等组件执行 SQL,返回结果;
  1. 提交 / 回滚事务:sqlSession.commit()或rollback();
  1. 关闭SqlSession:sqlSession.close()释放资源。

57. 什么是 MyBatis 的接口绑定,有什么好处?

  • 接口绑定:将Mapper接口与Mapper XML(或注解)绑定,无需编写接口实现类,调用接口方法即可执行对应 SQL。
好处
  1. 简化代码:省去手动实现Mapper接口的代码(传统 JDBC 需写实现类调用 SQL);
  1. 类型安全:编译时检查方法参数、返回值类型,避免运行时错误;
  1. 解耦:SQL 与 Java 代码分离(XML 中写 SQL),便于维护和优化;
  1. 支持动态 SQL:结合 XML 标签实现复杂 SQL 逻辑,灵活性高。

58. MyBatis 的编程步骤?

  1. 添加依赖:引入mybatis、数据库驱动(如 MySQL)依赖;
  1. 编写全局配置文件(mybatis-config.xml):配置数据源、事务管理器、Mapper 扫描;
  1. 定义实体类(如User):与数据库表映射;
  1. 编写Mapper接口(如UserMapper):声明 CRUD 方法;
  1. 编写Mapper XML(如UserMapper.xml):绑定接口方法,编写 SQL(select/insert等);
  1. 编码调用
 

// 加载配置,创建SqlSessionFactory

InputStream is = Resources.getResourceAsStream("mybatis-config.xml");

SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);

// 获取SqlSession,调用Mapper

try (SqlSession session = factory.openSession()) {

UserMapper mapper = session.getMapper(UserMapper.class);

User user = mapper.selectById(1); // 执行查询

}

59. JDBC 编程有哪些不足之处,MyBatis 是如何解决这些问题的?

JDBC 不足

MyBatis 解决方案

频繁创建 / 关闭连接(开销大)

集成连接池(如 Druid),复用连接

SQL 硬编码在 Java 代码中

SQL 写在 XML / 注解中,与代码分离

参数设置繁琐(setInt()等)

#{}占位符自动设置参数,支持 OGNL 表达式

结果集解析繁琐(rs.getString())

结果映射(resultMap)自动映射到实体类

事务管理手动控制(commit())

集成 Spring 事务管理,声明式控制

无缓存机制

提供一级、二级缓存,减少数据库访问

60. MyBatis 的优缺点?

优点
  1. 灵活:SQL 完全可控,适合复杂查询(存储过程、多表关联);
  1. 简化 JDBC:自动处理参数设置、结果映射,减少样板代码;
  1. 低侵入:无需继承特定类,POJO 与 Mapper 接口即可;
  1. 支持动态 SQL:通过标签简化 SQL 拼接;
  1. 缓存机制:一级、二级缓存提升查询性能。
缺点
  1. SQL 编写工作量大:简单 CRUD 也需写 SQL(不如 JPA 自动生成);
  1. 数据库移植性差:SQL 依赖数据库方言(如 MySQL 的LIMIT、Oracle 的ROWNUM);
  1. 维护成本高:XML 配置较多,大型项目需规范 SQL 管理。

http://www.dtcms.com/a/297684.html

相关文章:

  • k8s 中的 deployment,statefulset,daemonset 控制器的区别
  • 特征值与特征向量
  • 腾讯云CodeBuddy+微信小程序:5分钟开发番茄小闹钟
  • 电科金仓新一代数据库一体机:国产化方案替换优质选择
  • 本地内网IP映射到公网访问如何实现?内网端口映射外网工具有哪些?
  • python学习DAY22打卡
  • 深入解析Hadoop高频面试题:HDFS读/写流程的RPC调用链
  • yolov8通道级剪枝讲解(超详细思考版)
  • 解密负载均衡:如何轻松提升业务性能
  • JS事件流
  • 疯狂星期四第19天运营日记
  • 网络资源模板--基于Android Studio 实现的天气预报App
  • LeetCode 127:单词接龙
  • 三维图像识别中OpenCV、PCL和Open3D结合的主要技术概念、部分示例
  • 水库大坝安全监测的主要内容
  • MySQL 全新安装步骤(Linux版yum源安装)
  • Lua(面向对象)
  • 深度学习水论文:特征提取
  • NBIOT模块 BC28通过MQTT协议连接到EMQX
  • 如何在 Ubuntu 24.04 或 22.04 上安装和使用 GDebi
  • 智能网关:物联网时代的核心枢纽
  • ABP VNext + Razor 邮件模板:动态、多租户隔离、可版本化的邮件与通知系统
  • 智能网关芯片:物联网连接的核心引擎
  • 酷暑来袭,科技如何让城市清凉又洁净?
  • 制造业低代码平台实战评测:简道云、钉钉宜搭、华为云Astro、金蝶云·苍穹、斑斑低代码,谁更值得选?
  • 使用 FFmpeg 实现 RTP 音频传输与播放
  • 【Redis】初识Redis(定义、特征、使用场景)
  • Spring框架
  • 认识编程(3)-语法背后的认知战争:类型声明的前世今生
  • vue3单页面连接多个websocket并实现断线重连功能