Spring 全家桶原理
2026/4/18大约 7 分钟Java面试SpringSpringBootSpringCloudIOCAOP
Spring 全家桶原理
Spring IOC/AOP 原理、Spring Boot 自动装配、Spring Cloud 微服务组件、Spring Security——阿里 P6/P7 Spring 体系必考。
核心原理
Spring IOC 容器与 Bean 生命周期
Bean 完整生命周期(面试最常考):
实例化(Instantiation)
↓ 构造器调用
属性填充(Populate Properties)
↓ @Autowired / @Value 注入
Aware 回调
↓ BeanNameAware / BeanFactoryAware / ApplicationContextAware
BeanPostProcessor#postProcessBeforeInitialization
↓ 前置处理(如 @PostConstruct 注解处理器)
初始化(InitializingBean#afterPropertiesSet / @Bean(initMethod))
BeanPostProcessor#postProcessAfterInitialization
↓ 后置处理 ← AOP 代理在这里创建!
就绪(可被使用)
↓
销毁(DisposableBean#destroy / @PreDestroy / @Bean(destroyMethod))三级缓存解决循环依赖:
// Spring 的三级缓存(DefaultSingletonBeanRegistry)
Map<String, Object> singletonObjects; // 一级:完整 Bean(已初始化)
Map<String, Object> earlySingletonObjects; // 二级:早期引用(已实例化未初始化)
Map<String, ObjectFactory<?>> singletonFactories; // 三级:Bean 工厂(用于生成代理)
// 解决循环依赖流程:A 依赖 B,B 依赖 A
// 1. 创建 A:实例化 → 放入三级缓存(工厂)
// 2. 填充 A 的属性,发现需要 B
// 3. 创建 B:实例化 → 放入三级缓存
// 4. 填充 B 的属性,发现需要 A → 从三级缓存获取 A 的工厂 → 生成 A 的早期引用 → 放入二级缓存
// 5. B 初始化完成,放入一级缓存
// 6. A 获得 B 的引用,完成初始化,放入一级缓存下图以流程图展示了 Bean 从实例化到销毁的完整生命周期,AOP 代理在 BeanPostProcessor 后置处理阶段创建:
下图展示了三级缓存解决 A→B→A 循环依赖的时序过程:
注意: 构造器注入的循环依赖无法解决(对象尚未实例化就需要依赖,三级缓存无效);prototype 作用域的循环依赖也无法解决。
Spring AOP 原理
Spring AOP 是基于代理的 AOP,不修改字节码:
// 代理选择策略(Spring Boot 2.x 起默认使用 CGLIB)
// 1. 目标类实现了接口 + 未强制 CGLIB → JDK 动态代理
// Proxy.newProxyInstance(classLoader, interfaces, InvocationHandler)
// 2. 目标类无接口 / proxyTargetClass=true → CGLIB 子类代理
// Enhancer.create(targetClass, MethodInterceptor)
// 切面执行顺序(JDK 8 后 @Order 生效)
@Around → @Before → 目标方法 → @Around(proceed 后)→ @After → @AfterReturning/@AfterThrowing@Transactional 失效的 8 个场景(阿里高频):
@Service
public class OrderService {
// ❌ 场景1:同类内部调用(不经过代理)
public void createOrder() {
this.doCreate(); // this 直接调用,绕过代理
}
@Transactional
public void doCreate() { /* 事务不生效 */ }
// ❌ 场景2:方法非 public
@Transactional
protected void privateMethod() { /* 不生效 */ }
// ❌ 场景3:异常被吞掉
@Transactional
public void swallowException() {
try { riskyOp(); }
catch (Exception e) { log.error("ignored"); } // 异常被吞,不回滚
}
// ❌ 场景4:异常类型不匹配(默认只回滚 RuntimeException)
@Transactional
public void checkedException() throws IOException {
throw new IOException("checked"); // 默认不回滚!
// 解决:@Transactional(rollbackFor = Exception.class)
}
// ❌ 场景5:多线程(子线程无事务上下文)
@Transactional
public void asyncOp() {
new Thread(() -> saveData()).start(); // 子线程无事务
}
}高频面试题
Q: Spring Boot 自动装配原理?(字节/阿里 必问)
核心:
@SpringBootApplication=@EnableAutoConfiguration+@ComponentScan+@SpringBootConfiguration自动装配流程:
@EnableAutoConfiguration引入AutoConfigurationImportSelectorAutoConfigurationImportSelector.selectImports()调用SpringFactoriesLoader.loadFactoryNames()- 读取所有 jar 包中
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports(Spring Boot 2.7 以前是META-INF/spring.factories)- 加载所有
AutoConfiguration类,但通过@ConditionalOnClass、@ConditionalOnMissingBean、@ConditionalOnProperty等条件注解按需装配下图描述了 Spring Boot 自动装配从启动到按需加载 Bean 的完整流程:
// 自定义 starter 示例: // 1. 创建自动配置类 @Configuration @ConditionalOnClass(RedisTemplate.class) // 类路径存在 RedisTemplate 才生效 @ConditionalOnProperty(prefix = "myredis", name = "enabled", matchIfMissing = true) @EnableConfigurationProperties(MyRedisProperties.class) public class MyRedisAutoConfiguration { @Bean @ConditionalOnMissingBean(MyRedisClient.class) // 用户未自定义时才创建 public MyRedisClient myRedisClient(MyRedisProperties props) { return new MyRedisClient(props.getHost(), props.getPort()); } } // 2. 在 META-INF/spring/xxx.AutoConfiguration.imports 注册: // com.example.MyRedisAutoConfiguration
Q: Spring Cloud 核心组件与选型(2025 最新)?(腾讯/美团 微服务必考)
Spring Cloud Alibaba(国内主流)技术栈:
功能 组件 说明 服务注册/发现 Nacos Discovery 支持 AP/CP 切换,配置与注册二合一 配置中心 Nacos Config 动态刷新,支持灰度发布 负载均衡 Spring Cloud LoadBalancer 替代已停维护的 Ribbon 服务调用 OpenFeign 声明式 HTTP 客户端 熔断/限流 Sentinel 替代 Hystrix,实时监控、规则动态推送 分布式事务 Seata AT/TCC/SAGA 模式 网关 Spring Cloud Gateway 替代 Zuul,基于 WebFlux 响应式 OpenFeign + Sentinel 整合(熔断降级):
@FeignClient(name = "order-service", fallback = OrderFeignFallback.class) public interface OrderFeignClient { @GetMapping("/orders/{id}") OrderVO getOrder(@PathVariable Long id); } @Component public class OrderFeignFallback implements OrderFeignClient { @Override public OrderVO getOrder(Long id) { return OrderVO.defaultOrder(); // 降级返回默认值 } }
Q: Spring IOC 中 @Autowired、@Resource、@Inject 的区别?(阿里)
注解 来源 注入方式 多候选时 @AutowiredSpring 默认按类型(byType) 配合 @Qualifier按名称@ResourceJSR-250(Jakarta EE) 默认按名称(byName),找不到再按类型 可指定 name属性@InjectJSR-330 按类型(同 @Autowired)配合 @Named按名称实际推荐: 推荐
@Autowired+@Qualifier(Spring 原生,功能最完整);或构造器注入(最佳实践,易于测试、明确依赖):// 构造器注入(推荐) @Service public class OrderService { private final UserService userService; private final StockService stockService; // Spring 4.3+ 单构造器可省略 @Autowired public OrderService(UserService userService, StockService stockService) { this.userService = userService; this.stockService = stockService; } }
Q: Spring 事务的传播行为如何理解?NESTED 和 REQUIRES_NEW 的区别?(腾讯必问)
7 种传播行为中最常考的 3 种:
REQUIRED(默认):有事务则加入,无则新建。最常用,保证方法在同一事务内。REQUIRES_NEW:总是新建独立事务,挂起当前事务。新事务的提交/回滚与外层无关。适合:发送通知、记录日志(不受主业务回滚影响)。NESTED:嵌套事务,在外层事务的 Savepoint 上运行。内层可独立回滚到 Savepoint(外层不受影响),但外层回滚会导致内层也回滚。// 典型场景:REQUIRES_NEW @Transactional public void createOrder(Order order) { orderDao.save(order); notificationService.send(order); // 通知失败不影响下单 } @Service public class NotificationService { @Transactional(propagation = Propagation.REQUIRES_NEW) public void send(Order order) { // 即使这里抛异常,createOrder 的事务也不受影响 messageDao.save(buildMessage(order)); } }
Q: Spring Security 认证授权流程?JWT 无状态认证如何实现?(字节/美团)
Spring Security 过滤器链(关键过滤器):
SecurityContextPersistenceFilter → UsernamePasswordAuthenticationFilter → JwtAuthenticationFilter(自定义)→ ExceptionTranslationFilter → FilterSecurityInterceptor(授权决策)JWT 无状态认证实现:
// 自定义 JWT 过滤器 @Component public class JwtAuthFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws ServletException, IOException { String token = resolveToken(req); if (token != null && jwtUtils.validateToken(token)) { String username = jwtUtils.getUsername(token); UserDetails user = userDetailsService.loadUserByUsername(username); UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities()); SecurityContextHolder.getContext().setAuthentication(auth); } chain.doFilter(req, res); } } // 注册过滤器(在 UsernamePasswordAuthenticationFilter 之前) @Configuration public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { return http .sessionManagement(s -> s.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class) .authorizeHttpRequests(a -> a .requestMatchers("/auth/**").permitAll() .anyRequest().authenticated()) .build(); } }
知识星球深度内容
完整大厂面经实录(字节/阿里/腾讯/美团)、简历 1v1 修改、每周高频题精讲,扫码加入「AI 工程师加速社区」知识星球 👉 立即加入
