Java 高频面试题:Spring 全家桶深度解析

📅 2026/8/6 10:38:11
Java 高频面试题:Spring 全家桶深度解析
Java 高频面试题Spring 全家桶深度解析附详细答案 目录IoC 与 DI 核心原理Bean 生命周期详解事务管理原理AOP 底层实现机制Spring Boot 自动配置Spring Cloud 核心组件常用注解深入理解经典面试真题一、IoC 与 DI 核心原理 ⭐⭐⭐⭐⭐1.1 控制反转概念传统开发模式: ┌─────────────┐ │ UserService │──→ new UserDao() ←紧耦合 └─────────────┘ 使用 IoC 后: ┌─────────────┐ ┌──────────────┐ │ UserService │◄─── │ IoC Container│ └─────────────┘ └──────────────┘ │ ▼ UserDao 对象被创建并注入好处✅ 降低耦合度✅ 提高可测试性✅ 便于扩展维护✅ 统一管理对象生命周期1.2 DI 依赖注入方式方式一构造器注入 ⭐推荐ServicepublicclassUserService{privatefinalUserRepositoryuserRepository;// ✅ 推荐方式 - 不可变依赖线程安全AutowiredpublicUserService(UserRepositoryuserRepository){this.userRepositoryuserRepository;}}优点保证依赖非空避免循环依赖便于单元测试方式二Setter 注入ServicepublicclassOrderService{privatePaymentServicepaymentService;// setter 注入可以修改引用AutowiredpublicvoidsetPaymentService(PaymentServicepaymentService){this.paymentServicepaymentService;}}方式三字段注入 ❌不推荐ServicepublicclassProductService{// ❌ 隐藏了依赖关系不利于测试AutowiredprivateRepositoryrepository;// 问题无法保证依赖不为 null}1.3 Spring Bean 容器启动流程1. ClassPathXmlApplicationContext 启动 ↓ 2. 加载配置文件 (BeanDefinitionReader) ↓ 3. 解析 Bean 定义 (BeanDefinition) ↓ 4. 注册到 BeanDefinitionRegistry ↓ 5. 预初始化 singletonFactories (提前暴露) ↓ 6. instantiationAwarePostProcessors (BeanPostProcessor) ↓ 7. 实例化 Bean ↓ 8. populateBean (属性注入) ↓ 9. initializeBean (初始化回调) ↓ 10. addBeanPostProcessors (后置处理) ↓ 11. 完成启动1.4 解决循环依赖示例ServicepublicclassUserService{AutowiredprivateGroupServicegroupService;// 引用 GroupService}ServicepublicclassGroupService{AutowiredprivateUserServiceuserService;// 引用 UserService}// ❌ 会抛出 CircularReferenceException// Spring 如何通过三级缓存解决/** * 第一级singletonObjects 单例缓存池 * 第二级earlySingletonObjects 早期缓存 (未初始化) * 第三级singletonFactories 工厂缓存 * * 步骤 * 1. User 实例化 → 放入三级缓存 * 2. User 填充 groupService → 需要创建 Group * 3. Group 实例化 → 放入三级缓存 * 4. Group 填充 userService → 从三级缓存获取 User 代理 * 5. Group 初始化完成 → 移入一级缓存 * 6. User 初始化完成 → 移入一级缓存 */二、Bean 生命周期详解 ⭐⭐⭐⭐⭐2.1 Bean 完整生命周期流程图bean 实例化 ├─ instantiateBean() │ └─ 创建对象 ├─ applyMergedBeanDefinitionPostProcessors() │ └─ BeanFactoryPostProcessor ├─ applyBeanPostProcessorsBeforeInstantiation() │ └─ BeanPostProcessor 前置 └─ createBeanInstance() └─ 构造器执行 bean 属性赋值 ├─ mergeProperties() ├─ applyBeanPostProcessorsBeforePropertyMapping() ├─ populateBean() │ └─ 属性注入 └─ applyBeanPostProcessorsAfterPropertyMapping() bean 初始化 ├─ invokeInitMethods() │ ├─ PostConstruct │ ├─ InitializingBean.afterPropertiesSet() │ └─ init-method 自定义方法 └─ postProcessAfterInitialization() └─ AOP 代理创建 bean 使用 └─ 单例复用 / 多例新建 bean 销毁 ├─ DisposableBean.destroy() └─ destroy-method 自定义方法2.2 重要回调方法顺序阶段方法说明实例化前InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation返回非 null 可跳过实例化实例化BeanUtils.instantiate调用构造器属性赋值前BeanPostProcessor.postProcessBeforePropertyDetection判断是否跳过赋值属性赋值AbstractAutowireCapableBeanClass.populateBean注入依赖属性赋值后InstantiationAwareBeanPostProcessor.postProcessAfterPropertiesSet可用于修改属性初始化前BeanPostProcessor.postProcessBeforeInitialization准备做 AOP 代理PostConstructAnnotatedElementUtils.findMergedAnnotationPostConstruct 标注方法InitializingBeanafterPropertiesSet框架接口方法init-methodinvoker.invoke自定义初始化方法初始化后BeanPostProcessor.postProcessAfterInitializationAOP 代理包装2.3 实战案例自定义处理器ComponentpublicclassMyBeanPostProcessorimplementsBeanPostProcessor{OverridepublicObjectpostProcessBeforeInitialization(Objectbean,StringbeanName)throwsBeansException{System.out.println(before: beanName);returnbean;}OverridepublicObjectpostProcessAfterInitialization(Objectbean,StringbeanName)throwsBeansException{System.out.println(after: beanName);// 这里可以进行 AOP 操作if(userService.equals(beanName)){returnProxy.newProxyInstance(bean.getClass().getClassLoader(),bean.getClass().getInterfaces(),(proxy,method,args)-{System.out.println(Method: method.getName());returnmethod.invoke(bean,args);});}returnbean;}}三、事务管理原理 ⭐⭐⭐⭐⭐3.1 Spring 事务类型编程式事务: ├── TransactionTemplate └── PlatformTransactionManager (手动控制) 声明式事务: └── Transactional ⭐ 推荐 ├── 基于 AOP 实现 ├── 代码侵入性低 └── 易维护3.2Transactional 参数详解Transactional(valuedataSource,// 事务管理器名称propagationPropagation.REQUIRED,// 传播行为isolationIsolation.DEFAULT,// 隔离级别rollbackForException.class,// 回滚异常noRollbackForIllegalArgumentException.class,// 不回滚异常timeout30// 超时时间 (秒))publicvoidupdateOrder(Orderorder){// ...}3.3 传播行为对比传播行为描述典型场景REQUIRED如果有事务则加入没有则新建默认最常用REQUIRES_NEW新建独立事务挂起当前事务记录日志不能受主事务影响NESTED嵌套事务部分操作失败只需回滚部分SUPPORTS支持当前事务没有则以非事务运行查询操作NOT_SUPPORTED非事务运行挂起当前事务性能优化场景NEVER必须在非事务中执行业务规则约束3.4 源码分析事务如何工作// 核心TransactionInterceptor.intercept()publicObjectinvoke(finalMethodInvocationinvocation)throwsThrowable{// 1. 获取事务属性TransactionAttributetxAttrgetTransactionAttributeSource().getTransactionAttribute(method,clazz);// 2. 获取事务管理器PlatformTransactionManagertmtransactionManager;// 3. 开始事务TransactionStatusstatustm.getTransaction(txAttr);try{// 4. 执行目标方法Objectresultinvocation.proceedWithInvocation();// 5. 提交事务if(txAttr.isRollbackOnly()){tm.rollback(status);}else{tm.commit(status);}returnresult;}catch(Throwableex){// 6. 回滚事务tm.rollback(status);throwex;}}// 底层调用AbstractPlatformTransactionManagerpublicfinalTransactionStatusgetTransaction(TransactionAttributeDefinitiondefinition){TransactionInfotransactionInfocreateTransactionIfNecessary();// ... 更多细节}3.5Transactional失效场景 ⚠️1. 自调用失效ServicepublicclassUserService{TransactionalpublicvoidinsertUser(Useruser){// 插入数据}publicvoidupdateUser(Useruser){insertUser(user);// ❌ 内部调用事务失效}}// 解决方案使用 AopContext.currentProxy()UserServiceproxy(UserService)AopContext.currentProxy();proxy.insertUser(user);// ✅ 通过代理调用事务生效2. 异常被捕获Transactionalpublicvoidtransfer(Accountfrom,Accountto,doubleamount){try{deductBalance(from,amount);addBalance(to,amount);}catch(Exceptione){// ❌ 吞掉异常不会触发回滚e.printStackTrace();}}// 正确做法Transactionalpublicvoidtransfer(Accountfrom,Accountto,doubleamount){try{deductBalance(from,amount);addBalance(to,amount);}catch(Exceptione){thrownewRuntimeException(e);// ✅ 抛出运行时异常}}3. 非 RuntimeException 不回滚Transactional(rollbackForException.class)publicvoidtest()throwsSQLException{// 必须指定 checked exception否则不回滚}3.6 隔离级别对比-- READ UNCOMMITTED (读未提交)-- 可以读到未提交的数据 → 脏读-- READ COMMITTED (读已提交) -- Oracle 默认-- 只能读到已提交的数据 → 解决脏读可能有幻读-- REPEATABLE READ (可重复读) -- MySQL 默认-- 同一事务内多次读取结果一致 → 解决脏读、不可重复读-- 通过 MVCC Next-Key Lock 解决幻读-- SERIALIZABLE (串行化)-- 所有事务串行执行 → 最高开销但完全隔离四、AOP 底层实现机制 ⭐⭐⭐⭐⭐4.1 AOP 核心概念Aspect (切面): 横切关注点封装 (如日志、事务) Pointcut (切点): 定义在哪里切入 Advice (通知): 在何处切入 (Before/After/Around...) Target (目标): 被代理的对象 Weaving (织入): 将切面应用到目标创建代理 ┌─────────────────────────────┐ │ AOP Container │ │ │ │ ┌─────────────┐ │ │ │ ProxyLogic │ ◄── Advice │ │ │ (AOP) │ │ │ └──────┬──────┘ │ │ │ │ │ ▼ │ │ ┌─────────────┐ │ │ │ TargetObj │ │ │ └─────────────┘ │ └─────────────────────────────┘4.2 JDK 动态代理 vs CGLIB特性JDK 动态代理CGLIB基于InterfaceClass生成方式Proxy.newProxyInstanceEnhancer.create()性能慢 (反射)快 (字节码)支持只能代理接口可代理类Final不受限无法代理 final 方法和类JDK 动态代理示例// 创建代理UserServiceImplservicenewUserServiceImpl();InvocationHandlerhandlernewInvocationHandler(){OverridepublicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{// BeforeSystem.out.println(Before: method.getName());// ExecuteObjectresultmethod.invoke(service,args);// AfterSystem.out.println(After: method.getName());returnresult;}};UserProxyproxy(UserProxy)Proxy.newProxyInstance(service.getClass().getClassLoader(),service.getClass().getInterfaces(),handler);proxy.save();// 输出 Before: save \n After: saveCGLIB 示例EnhancerenhancernewEnhancer();enhancer.setSuperclass(TargetClass.class);enhancer.setCallback(newMethodInterceptor(){OverridepublicObjectintercept(Objectobj,Methodmethod,Object[]args,MethodProxyproxy)throwsThrowable{System.out.println(Before);Objectresultproxy.invokeSuper(obj,args);System.out.println(After);returnresult;}});TargetClassinstance(TargetClass)enhancer.create();4.3 Spring AOP 策略选择ConfigurationEnableAspectJAutoProxy(proxyTargetClasstrue)// 强制使用 CGLIBpublicclassAppConfig{}// 规则// 1. 有接口 → 优先 JDK 动态代理// 2. 无接口 or proxyTargetClasstrue → 使用 CGLIB// 3. SpringBoot 2.x 默认 CGLIB4.4 Transactional 中的 AOPServicepublicclassOrderService{// Transactional 背后就是 AOP 实现的TransactionalpublicvoidplaceOrder(Orderorder){// 开启事务 → 执行 → 提交/回滚}}// Spring 内部创建代理拦截方法调用4.5 常见切点表达式// 1. 所有公共方法annotation(com.example.annotation.Log)// 2. 指定包下的所有类within(com.example.service.*)// 3. 任意修饰符和任意返回类型的公共方法execution(*com.example.service.*.*(..))// 4. 所有带 Log 注解的方法within(org.springframework.stereotype.Service)// 5. 所有 Service 类的所有方法target(org.springframework.stereotype.Service)五、Spring Boot 自动配置 ⭐⭐⭐⭐⭐5.1 自动配置原理SpringBootApplication └── EnableAutoConfiguration └── Import(AutoConfigurationImportSelector.class) └── selects auto-configurations └── load META-INF/spring.factories5.2 spring.factories 结构# src/main/resources/META-INF/spring.factories org.springframework.boot.autoconfigure.EnableAutoConfiguration\ org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\ org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\ org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration5.3 Conditional 条件注解ConfigurationConditionalOnClass(JdbcTemplate.class)// 类路径下有 JdbcTemplateConditionalOnMissingBean(DataSource.class)// 没有 DataSource 的 BeanAutoConfigureBefore(WebMvcAutoConfiguration.class)publicclassDataSourceAutoConfiguration{BeanConfigurationProperties(prefixspring.datasource)publicDataSourcedataSource(){returnDataSourceBuilder.create().build();}}5.4 Conditional 类型对比注解作用ConditionalOnClass存在指定类时生效ConditionalOnMissingClass不存在指定类时生效ConditionalOnProperty指定属性值为 true 时生效ConditionalOnBean容器中存在指定 Bean 时生效ConditionalOnMissingBean容器中不存在指定 Bean 时生效ConditionalOnSingleCandidate容器中只有一个候选者时生效5.5 自定义 Starter 示例project/ ├── src/ │ ├── main/ │ │ ├── java/ │ │ │ └── com/example/autoconfig/ │ │ │ ├── MyStarterAutoConfiguration.java │ │ │ └── MyProperties.java │ │ └── resources/ │ │ └── META-INF/ │ │ └── spring.factoriesConfigurationConditionalOnClass(MyComponent.class)AutoConfigureBeforepublicclassMyStarterAutoConfiguration{BeanConfigurationProperties(prefixmy.starter)publicMyPropertiesmyProperties(){returnnewMyProperties();}BeanConditionalOnMissingBeanpublicMyComponentmyComponent(MyPropertiesproperties){returnnewMyComponent(properties);}}六、Spring Cloud 核心组件6.1 微服务架构模式客户端请求 │ ▼ ┌───────────────┐ │ API Gateway │ └───────┬───────┘ │ ┌───┴───┐ ▼ ▼ ┌─────┐ ┌─────┐ │ Svc │ │ Svc │ │ A │ │ B │ └─────┘ └─────┘6.2 Spring Cloud Netflix 全家桶服务发现Eureka Discovery Server 负载均衡Ribbon Client 熔断器Hystrix Circuit Breaker 网关Zuul Gateway 配置中心Config 替代方案 (Spring Cloud Alibaba): ├── Nacos (服务注册 配置中心) ├── Sentinel (流量控制和熔断) ├── Seata (分布式事务) └── RocketMQ (消息队列)6.3 Feign 远程调用原理FeignClient(nameuser-service)publicinterfaceUserServiceClient{GetMapping(/users/{id})UsergetUserById(PathVariableLongid);}// 底层流程:// 1. 创建动态代理// 2. encodeUrl → 编码 URL// 3. RequestTemplate → 构建 HTTP 请求// 4. LoadBalancerRequestTransformer → 负载均衡// 5. execute() → HttpClient/Ribbon 发送请求七、常用注解深入理解7.1 Autowired vsResource特性AutowiredResource来源SpringJSR-250默认匹配byTypebyName支持注解only Autowiredname, type, requiredAutowiredprivateUserServiceuserService;// byTypeResource(nameuserService)privateUserServiceuserService;// byName7.2 Component vsBean vsServiceComponent// 通用组件RestController// Controller ResponseBodyService// Service 层专用Repository// DAO 层专用BeanpublicUserServiceuserService(){returnnewUserService();}// 用于配置类标记返回值作为 Bean7.3 Value 注入配置值Value(${app.name:default})privateStringappName;Value(#{${developers}.split(,)})privateListStringdevelopers;八、经典面试真题 Q1: Spring Bean 是线程安全的吗A:答Bean 本身不是线程安全的取决于 Scope: 1. Singleton (默认) └── 多线程共享一个实例 → 非线程安全 2. Prototype └── 每次请求新建实例 → 线程安全 3. Request/Session └── 特定范围共享 → 需根据具体情况 建议 - 保持 Bean 无状态 - 局部变量是线程安全的 - 避免使用实例变量存储请求数据Q2: Spring 如何处理异常A:三种方式: 1. ExceptionHandler Controller public class UserController { ExceptionHandler(UserNotFoundException.class) public ResponseEntity? handleNotFound(UserNotFoundException e) { return ResponseEntity.status(404).body(用户不存在); } } 2. ControllerAdvice ExceptionHandler ControllerAdvice public class GlobalExceptionHandler { ExceptionHandler(Exception.class) public ResponseEntity? handleAll(Exception e) { return ResponseEntity.status(500).body(系统错误); } } 3. 实现 HandlerExceptionResolver 接口Q3: Spring Boot starters 是什么A:Starter 是一系列依赖描述的集合简化 Maven/Gradle 配置。 特点: 1. 包含常用的依赖项 2. 自动配置 3. 版本统一管理 举例: - spring-boot-starter-web → web 应用必备 - spring-boot-starter-data-jpa → JPA 数据访问 - spring-boot-starter-security → 安全认证 创建自己的 starter: ① 定义 AutoConfiguration 类 ② 添加 spring.factories ③ 编写对应的 Properties 类 ④ 打包发布Q4: 如何解决跨域问题A:方式一CrossOrigin PostMapping(value /login, produces application/json) CrossOrigin(origins *) public ResponseEntity login(...) {} 方式二全局配置 Configuration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/api/**) .allowedOrigins(*) .allowedMethods(GET, POST, PUT, DELETE) .allowCredentials(true) .maxAge(3600); } } 方式三CrossOrigin 全局注解 参考资料《Spring 源码实战》Spring 官方文档Baeldung 教程Spring Blog 更多内容持续更新中…关注我获取更多技术干货如果觉得有用欢迎点赞收藏转发有任何问题欢迎评论区交流~