Spring面试高频题:从基础到源码,通俗拆解+避坑指南
本文拒绝晦涩难懂的源码堆砌用“通俗类比细节拆解面试真题”的方式把Spring面试中最常考、最易踩坑的知识点讲透不管是初级面试还是中级面试都能直接套用帮你轻松拿下Spring相关考题。一、Spring基础认知先搞懂“是什么、为什么用”面试第一道Spring题大概率是“你对Spring的理解是什么”很多人只会说“Spring是一个轻量级框架”这样的回答太敷衍根本拿不到高分。核心是要讲清“定位核心价值核心特性”用通俗的话让面试官明白你真的懂。1.1 核心定位通俗类比Spring的核心定位是一个轻量级的IoC容器 AOP框架本质是“帮我们管理对象、简化开发”。通俗类比以前我们写代码需要自己new对象、管理对象之间的依赖比如Service里需要Dao就要自己new DaoImpl()就像“自己做饭”——买菜、洗菜、做饭、洗碗全要自己来而Spring就像“一个全能管家”你告诉它需要什么对象它会帮你创建对象、管理对象之间的依赖你只需要专注于“业务逻辑”就像只负责吃不用管做饭和洗碗。1.2 为什么要用Spring面试高频核心是“解耦简化开发”具体有4个核心优势面试时要结合实际开发场景说不要只背理论解耦通过IoC容器管理对象消除对象之间的硬依赖不用再自己new对象比如Service和Dao的依赖由Spring注入后续替换Dao实现类不用修改Service代码。简化开发Spring提供了大量的工具类和封装比如事务管理、异常处理不用重复写冗余代码比如以前手动管理事务需要try-catchSpring一句注解就能搞定。高可扩展性支持AOP、自定义Bean、插件扩展比如集成MyBatis、Redis能轻松适配不同的业务场景。生态完善Spring家族有Spring Boot快速开发、Spring Cloud微服务、Spring Security安全等一套生态能覆盖后端开发的所有场景降低技术选型成本。1.3 核心概念拆解必记面试基础Spring的核心概念不多但每个都要吃透尤其是“IoC、DI、AOP、Bean”面试必问用通俗的话拆解如下IoC控制反转核心是“反转对象的创建权”——以前对象由开发者自己创建new现在由Spring容器创建并管理开发者只需要“被动接收”对象。比如以前你需要new UserService()现在Spring帮你创建好你直接用Autowired注入就能用。DI依赖注入IoC的具体实现方式指Spring容器将依赖的对象“注入”到需要的对象中。比如UserService需要UserDaoSpring会把UserDao对象注入到UserService中不用UserService自己创建。补充IoC是思想DI是实现面试时要区分开避免混淆BeanSpring容器管理的对象就是“被Spring管家照顾的对象”比如UserService、UserDao只要交给Spring管理就是Bean。AOP面向切面编程核心是“在不修改原有代码的前提下增强业务逻辑”比如日志记录、事务管理、权限校验这些通用功能可以做成“切面”织入到业务方法中不用在每个业务方法里重复写。1.4 Spring、Spring Boot、Spring Cloud的区别高频易混题很多面试会问三者的关系很多人分不清用“通俗类比表格”讲清一看就懂类比Spring是“地基”Spring Boot是“精装修的房子”Spring Cloud是“小区配套”——地基Spring打好了才能盖房子Spring Boot房子盖好后需要小区的配套设施Spring Cloud才能满足日常需求。框架核心作用通俗理解Spring提供IoC、AOP核心能力是基础框架负责管理对象和依赖地基所有Spring家族的基础Spring Boot基于Spring简化配置自动配置快速搭建项目无需手动整合依赖精装修房子拎包入住不用自己装修配置Spring Cloud基于Spring Boot提供微服务相关组件注册中心、网关、配置中心等小区配套比如快递柜、超市满足微服务的协同需求总结Spring是基础Spring Boot简化Spring开发Spring Cloud基于Spring Boot实现微服务三者不是替代关系而是互补关系。二、Spring核心原理面试深挖考点吃透不慌基础概念问完面试官一定会深挖核心原理这部分是“拉开差距”的关键重点掌握3个核心IoC容器原理、Bean生命周期、AOP原理每个都要讲清“原理细节面试考点”。2.1 IoC容器原理面试高频深挖核心问题Spring IoC容器是怎么创建和管理Bean的流程是什么通俗理解IoC容器就像“Spring的对象仓库”它的核心工作是“扫描Bean→创建Bean→注入依赖→管理Bean”整个流程分为3步细节要记牢面试时要能说出完整流程核心流程3步走扫描Bean定位Spring启动时会扫描指定包下比如ComponentScan注解指定的包所有带有Component、Service、Controller、Repository注解的类将这些类标记为“需要被管理的Bean”并记录类的信息比如类名、依赖关系。创建Bean初始化Spring根据扫描到的类信息通过“反射”创建Bean对象默认是单例后续会讲单例和多例创建过程中会执行Bean的构造方法、初始化方法。注入依赖装配Bean创建完成后Spring会检查Bean是否有依赖比如Autowired注解的属性如果有就从容器中找到对应的Bean注入到当前Bean中完成依赖装配。关键细节面试避坑点IoC容器的核心接口BeanFactory和ApplicationContext两者的区别是面试高频题记清楚BeanFactory最基础的IoC容器采用“懒加载”只有获取Bean时才创建Bean功能简单适合简单场景。ApplicationContextBeanFactory的子接口采用“预加载”Spring启动时就创建所有单例Bean提供更多功能比如国际化、事件监听、资源加载实际开发中几乎都用ApplicationContext比如ClassPathXmlApplicationContext、AnnotationConfigApplicationContext。Bean的创建方式除了注解扫描还有3种方式面试可能会问XML配置bean iduserService classcom.example.UserService/传统方式现在很少用但面试可能考。Bean注解在配置类中用Bean注解方法方法返回值就是Bean比如整合第三方框架时常用。工厂方法通过实现FactoryBean接口自定义Bean的创建逻辑进阶考点了解即可。2.2 Bean的生命周期面试重中之重核心问题Spring Bean从创建到销毁整个生命周期有哪些步骤很多人记不全用“通俗步骤细节”帮你记住通俗理解Bean的生命周期就像“一个人的一生”——从“出生”创建→“成长”初始化→“工作”被使用→“死亡”销毁整个流程分为7步每一步都有面试考点Bean生命周期完整步骤带细节实例化Bean出生Spring通过反射调用Bean的无参构造方法创建Bean对象此时Bean只是一个空对象属性还未赋值。 注意如果Bean没有无参构造方法会报错InstantiationException面试常考“Bean实例化失败的原因”这是一个坑。设置Bean属性赋值Spring将容器中对应的依赖注入到Bean的属性中比如Autowired注入的UserDao就是在这一步赋值的。调用BeanNameAware的setBeanName方法如果Bean实现了BeanNameAware接口Spring会将Bean的id名称传入该方法让Bean知道自己在容器中的名称。调用BeanFactoryAware的setBeanFactory方法如果Bean实现了BeanFactoryAware接口Spring会将IoC容器本身传入该方法让Bean能直接操作容器实际开发中很少用但面试会问。调用InitializingBean的afterPropertiesSet方法如果Bean实现了InitializingBean接口Spring会在Bean属性赋值完成后调用该方法用于执行Bean的初始化逻辑比如初始化数据库连接。 补充也可以用PostConstruct注解替代该接口更简洁实际开发常用。Bean就绪工作此时Bean已经创建完成、属性赋值完成、初始化完成能够被开发者使用比如通过Autowired注入后调用方法。Bean销毁死亡当Spring容器关闭时会调用Bean的销毁方法释放资源比如关闭数据库连接。 补充可以通过实现DisposableBean接口的destroy方法或用PreDestroy注解定义销毁逻辑。关键细节面试避坑点初始化方法的执行顺序PostConstruct注解 InitializingBean接口的afterPropertiesSet方法 XML配置中的init-method属性如果同时存在按这个顺序执行。销毁方法的执行顺序PreDestroy注解 DisposableBean接口的destroy方法 XML配置中的destroy-method属性。单例Bean和多例Bean的生命周期区别单例Bean的生命周期和容器一致容器启动创建容器关闭销毁多例Bean每次被获取时创建使用完后由JVM垃圾回收Spring不管理多例Bean的销毁。2.3 AOP原理面试高频必吃透核心问题Spring AOP是怎么实现的动态代理有两种方式区别是什么通俗理解AOP就像“给业务方法加一层‘滤镜’”——不用修改业务方法的代码就能在方法执行前、执行中、执行后添加通用逻辑比如日志、事务而这层“滤镜”的实现核心就是动态代理。AOP核心原理动态代理两种方式Spring AOP的底层实现有两种动态代理方式Spring会自动选择面试时要能说出两种方式的区别、适用场景还要知道“为什么Spring会这么选”动态代理方式实现原理适用场景优点/缺点JDK动态代理基于Java反射机制通过Proxy类创建目标对象的接口代理只能代理实现了接口的类目标类实现了接口优点原生支持创建速度快缺点只能代理接口无法代理类方法CGLIB动态代理基于字节码技术生成目标类的子类不用实现接口直接代理类目标类没有实现接口或需要代理类方法优点无需接口执行速度快缺点不能代理final类/方法创建速度较慢AOP核心流程通俗拆解定义切面Aspect比如日志切面、事务切面里面包含通知增强逻辑和切入点哪些方法需要被增强。Spring扫描切面解析切入点表达式找到需要被增强的目标方法。Spring根据目标类是否实现接口选择对应的动态代理方式JDK/CGLIB创建目标对象的代理对象。当调用目标方法时实际调用的是代理对象的方法代理对象会先执行切面的通知逻辑比如前置通知再执行目标方法最后执行后置通知完成增强。关键细节面试避坑点AOP的5种通知类型记牢面试常考前置通知Before目标方法执行前执行比如日志记录方法开始时间。后置通知After目标方法执行后执行无论方法是否异常都会执行比如记录方法结束时间。返回通知AfterReturning目标方法正常返回后执行比如记录方法返回值。异常通知AfterThrowing目标方法抛出异常后执行比如记录异常信息。环绕通知Around包裹目标方法可在方法执行前、执行中、执行后自定义逻辑最灵活比如事务管理。Spring Boot 2.x后默认使用CGLIB动态代理即使目标类实现了接口可以通过配置spring.aop.proxy-target-classfalse强制使用JDK动态代理。AOP的坑final方法、private方法无法被增强因为CGLIB无法生成final类的子类JDK动态代理也无法代理private方法面试常考“为什么我的AOP不起作用”这是常见坑。三、Spring面试高频题真题通俗解析避坑这部分是核心整理了Spring面试中最常考的10道题每道题都包含“真题通俗解析避坑点”直接背就能用避免面试时答非所问。3.1 真题1Spring IoC和DI的区别是什么初级必问解析通俗版IoC是“思想”DI是“实现”IoC说的是“反转对象创建权”让Spring管理对象DI说的是“反转依赖注入”让Spring把依赖的对象注入到需要的地方。比如你需要UserServiceSpring帮你创建UserService这是IoCUserService需要UserDaoSpring把UserDao注入到UserService这是DI。避坑点不要说“IoC和DI是一回事”也不要混淆两者的关系记住“IoC是思想DI是实现”即可。3.2 真题2Spring Bean的作用域有哪些初级必问解析重点记前2个后3个了解即可Bean的作用域指的是“Bean在IoC容器中的创建方式和生命周期”共5种singleton单例默认Spring容器中只有一个Bean实例所有请求都共享这个实例比如Service、Dao实际开发中最常用。 避坑点单例Bean是线程不安全的如果Bean中有成员变量多线程并发修改会出问题解决方案不用成员变量或用ThreadLocal、锁机制。prototype多例每次获取Bean时Spring都会创建一个新的Bean实例比如ControllerSpring Boot中Controller默认是单例但若有成员变量可设置为多例。 避坑点多例BeanSpring不管理销毁需要自己手动释放资源。request请求域每个HTTP请求创建一个新的Bean仅在当前请求中有效Web场景专用。session会话域每个HTTP会话创建一个新的Bean仅在当前会话中有效Web场景专用。globalSession全局会话域仅在Portlet门户场景中有效现在几乎不用。3.3 真题3Autowired和Resource的区别是什么中级必问解析通俗版两者都是用来注入依赖的但来源、匹配方式、支持的参数不同用表格对比最清晰对比维度AutowiredResource来源Spring自带注解JDK自带注解javax.annotation.Resource匹配方式先按类型byType匹配再按名称byName匹配先按名称byName匹配再按类型byType匹配支持参数支持requiredfalse注入失败不报错支持name属性指定注入Bean的名称适用场景Spring项目中通用推荐使用需要跨框架比如SpringJDK或指定Bean名称时使用避坑点Autowired默认按类型匹配如果容器中有多个同类型的Bean会报错解决方案用Qualifier注解指定Bean名称比如Autowired Qualifier(userDaoImpl1)。3.4 真题4Spring事务管理的核心原理是什么中级必问解析通俗版Spring事务管理的核心是“AOP动态代理”把事务逻辑开启事务、提交事务、回滚事务做成切面织入到业务方法中无需手动写事务代码。关键细节必记事务的传播机制面试高频记清楚7种重点记前4种REQUIRED默认如果当前有事务就加入事务如果没有就创建一个新事务比如Service方法调用Dao方法Dao的事务会加入Service的事务。SUPPORTS如果当前有事务就加入事务如果没有就以非事务方式执行很少用。MANDATORY必须在事务中执行否则报错很少用。REQUIRES_NEW无论当前是否有事务都创建一个新事务原有事务暂停比如转账时日志记录的事务要独立即使转账失败日志也要记录。NOT_SUPPORTED以非事务方式执行如果当前有事务就暂停事务很少用。NEVER以非事务方式执行如果当前有事务就报错很少用。NESTED如果当前有事务就创建一个嵌套事务子事务依赖父事务父事务回滚子事务也回滚子事务回滚父事务不回滚。事务的隔离级别对应数据库的隔离级别记4种DEFAULT默认继承数据库的隔离级别MySQL默认是REPEATABLE READ。READ_UNCOMMITTED读未提交会出现脏读、不可重复读、幻读最低级别不用。READ_COMMITTED读已提交避免脏读会出现不可重复读、幻读Oracle默认。REPEATABLE READ可重复读避免脏读、不可重复读会出现幻读MySQL默认。SERIALIZABLE串行化避免所有问题但性能极差不用。避坑点Spring事务默认只回滚RuntimeException运行时异常 checked异常比如IOException不会回滚解决方案在Transactional注解中指定rollbackFor{Exception.class}让所有异常都回滚。3.5 真题5Spring Boot自动配置的原理是什么中级必问解析通俗版Spring Boot的核心是“自动配置”不用手动写XML配置就能整合各种框架核心原理是“EnableAutoConfiguration注解 自动配置类 条件注解”。核心流程3步Spring Boot启动时SpringBootApplication注解会包含EnableAutoConfiguration注解该注解会开启自动配置。EnableAutoConfiguration会扫描Spring Boot内置的自动配置类位于spring-boot-autoconfigure.jar的META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件中。每个自动配置类比如DataSourceAutoConfiguration、MyBatisAutoConfiguration都会通过条件注解比如ConditionalOnClass、ConditionalOnMissingBean判断是否需要生效生效后会自动配置对应的Bean比如数据源Bean。避坑点自动配置类生效的条件是“引入对应的依赖”比如要让MyBatisAutoConfiguration生效必须引入mybatis-spring-boot-starter依赖否则自动配置不生效。3.6 真题6Spring Bean的循环依赖怎么解决高级必问解析通俗版循环依赖就是“两个Bean互相依赖”比如A依赖BB依赖ASpring默认能解决“单例Bean的循环依赖”核心是“三级缓存”。三级缓存记清楚面试必问一级缓存singletonObjects存储已经创建完成、初始化完成的单例Bean最终供开发者使用。二级缓存earlySingletonObjects存储已经实例化、但未初始化的单例Bean用于解决循环依赖提前暴露Bean。三级缓存singletonFactories存储Bean的工厂方法用于创建Bean的早期实例如果Bean有AOP增强会在这里生成代理对象。循环依赖解决流程A依赖BB依赖ASpring创建A实例化A无参构造将A的工厂方法放入三级缓存此时A未初始化、未赋值。A需要注入BSpring去创建B实例化B将B的工厂方法放入三级缓存此时B未初始化、未赋值。B需要注入ASpring从三级缓存中获取A的工厂方法创建A的早期实例未初始化放入二级缓存删除三级缓存中的A。B注入A完成初始化放入一级缓存删除二级缓存中的A。A注入B完成初始化放入一级缓存删除三级缓存中的B。避坑点Spring只能解决“单例Bean的循环依赖”多例Bean的循环依赖无法解决会报错如果Bean有构造方法注入也无法解决循环依赖因为构造方法注入会在实例化时就需要依赖而三级缓存是在实例化后才暴露。3.7 真题7Spring AOP和AspectJ的区别是什么高级必问解析通俗版两者都是AOP框架但实现方式、适用场景不同核心区别是“织入时机不同”Spring AOP基于动态代理JDK/CGLIB运行时织入Spring启动后创建代理对象时织入切面只能增强Spring管理的Bean功能相对简单适合大多数业务场景。AspectJ基于字节码修改编译时织入编译Java文件时就将切面织入到目标类中可以增强任何类不限于Spring Bean功能强大但配置复杂适合需要复杂AOP增强的场景。避坑点Spring AOP默认不支持AspectJ的切入点表达式比如within、execution的复杂用法需要引入aspectjweaver依赖才能支持。3.8 真题8Component和Bean的区别是什么初级必问解析通俗版两者都是用来创建Bean的但作用范围、使用场景不同Component作用于类上是“注解驱动”的Bean创建方式Spring会扫描该类自动创建Bean默认Bean名称是类名首字母小写适合自己写的类。Bean作用于方法上是“手动配置”的Bean创建方式方法的返回值就是Bean适合整合第三方框架比如整合Redis、MyBatis第三方类无法添加Component注解。例子自己写的UserService用Component整合Redis的RedisTemplate用Bean注解方法返回RedisTemplate对象。3.9 真题9Spring Boot的 Starter 是什么初级必问解析通俗版Starter是Spring Boot的“依赖包集合”本质是“简化依赖配置”比如mybatis-spring-boot-starter里面包含了MyBatis、Spring MyBatis、数据源等相关依赖不用手动一个个引入只需引入一个Starter就能整合MyBatis。核心作用减少依赖配置实现“一键整合”让开发者专注于业务开发不用关注依赖的版本兼容Starter会帮我们管理依赖版本避免版本冲突。避坑点不同的Starter对应不同的框架比如spring-boot-starter-web是整合Spring MVC的spring-boot-starter-jdbc是整合JDBC的不要引入错误的Starter。3.10 真题10Spring Bean的初始化和销毁方法有哪些方式初级必问解析记3种常用方式按优先级排序注解方式最常用PostConstruct初始化方法、PreDestroy销毁方法作用于方法上方法名可以自定义。接口方式实现InitializingBean接口重写afterPropertiesSet方法初始化、实现DisposableBean接口重写destroy方法销毁。XML配置方式传统方式现在很少用在XML中配置init-method和destroy-method属性指定初始化和销毁方法。避坑点初始化方法会在Bean属性赋值完成后执行销毁方法会在Spring容器关闭时执行多例Bean的销毁方法不会被Spring调用需要手动处理。四、Spring实战避坑生产环境高频问题及解决方案很多开发者在本地测试Spring项目时一切正常但部署到生产环境后会遇到各种问题以下是生产环境中最常见的5个坑附具体解决方案面试时如果能说出这些会加分很多。4.1 坑1单例Bean线程不安全最常见现象多线程并发调用单例Bean的方法时出现数据错乱比如成员变量被篡改。原因单例Bean在容器中只有一个实例多线程共享该实例若Bean中有可变成员变量会出现线程安全问题。解决方案避免使用可变成员变量优先推荐比如把变量放在方法内部作为局部变量。使用ThreadLocal存储成员变量每个线程有独立的变量副本互不影响。将Bean改为多例prototype但会增加Bean创建的开销谨慎使用。使用锁机制比如synchronized但会影响性能适合并发量低的场景。4.2 坑2Spring事务不生效高频坑现象方法上添加了Transactional注解但事务没有回滚比如报错后数据库数据依然被修改。常见原因及解决方案注解标注错误Transactional注解标注在非public方法上Spring事务只对public方法生效改为public方法。异常类型不匹配Spring默认只回滚RuntimeException若方法抛出checked异常比如IOException需在Transactional中添加rollbackFor{Exception.class}。自调用问题同一个Bean中无事务的方法调用有事务的方法事务不生效因为自调用不会经过代理对象解决方案将有事务的方法抽成独立的Bean或通过AopContext获取代理对象调用。未开启事务管理Spring Boot需要EnableTransactionManagement注解开启事务管理Spring Boot 2.x后若引入spring-boot-starter-jdbc会自动开启无需手动添加。4.3 坑3AOP不起作用高频坑现象编写了AOP切面但目标方法执行时切面逻辑没有执行。常见原因及解决方案切面类没有添加Aspect注解或没有被Spring扫描到需添加Component注解确保切面类在ComponentScan扫描范围内。切入点表达式错误没有匹配到目标方法比如包名、方法名写错建议用execution表达式精准匹配比如execution(* com.example.service.*.*(..))。目标方法是final或private方法CGLIB无法代理final方法JDK无法代理private方法修改方法为非final、public方法。自调用问题同一个Bean中方法自调用AOP不生效原因同事务自调用解决方案抽成独立Bean或获取代理对象调用。4.4 坑4循环依赖导致Bean创建失败现象Spring启动时报错“Circular reference”循环依赖Bean创建失败。常见原因及解决方案多例Bean循环依赖Spring无法解决多例Bean的循环依赖将多例Bean改为单例Bean或打破循环依赖比如通过第三方Bean中转。构造方法注入循环依赖将构造方法注入改为Autowired字段注入或setter方法注入。复杂循环依赖通过Lazy注解延迟加载依赖比如Autowired Lazy private B b;让Bean在使用时才创建打破循环依赖。4.5 坑5自动配置不生效现象引入了Starter依赖但自动配置的Bean没有被创建比如引入mybatis-spring-boot-starter但RedisTemplate无法注入。常见原因及解决方案引入的Starter错误比如要整合MyBatis却引入了spring-boot-starter-jdbc替换为正确的Starter。自动配置类被排除比如SpringBootApplication(exclude DataSourceAutoConfiguration.class)导致数据源自动配置不生效删除exclude属性。条件注解不满足比如DataSourceAutoConfiguration需要引入数据源依赖mysql-connector-java且配置了spring.datasource相关参数补充依赖和配置。五、总结Spring学习与面试建议Spring面试的核心不是背源码而是“理解原理掌握细节结合实战”很多开发者面试翻车不是因为不懂而是因为“懂皮毛不懂细节”结合自身经验给大家以下学习和面试建议入门阶段先掌握基础概念IoC、DI、AOP、Bean学会用Spring Boot快速搭建项目熟悉常用注解Component、Autowired、Transactional能完成简单的业务开发。进阶阶段吃透核心原理Bean生命周期、AOP动态代理、IoC容器流程、事务管理重点记细节和避坑点能解释面试题的底层逻辑而不是死记硬背。面试准备重点掌握本文整理的10道高频题结合实战避坑点面试时不要只说理论要结合实际开发场景比如“我在项目中遇到过事务不生效的问题原因是XXX解决方案是XXX”这样更有说服力。最后提醒Spring的知识点看似多但核心围绕“IoC和AOP”展开只要抓住这两个核心再逐步拆解细节、掌握避坑点就能轻松应对Spring面试。希望本文能帮你吃透Spring面试知识点少走弯路面试顺利拿下offer如果觉得有收获欢迎点赞、收藏也可以在评论区分享你的Spring面试经验
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2434035.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!