疯狂餐厅
86.88M · 2026-03-21
作为 Java 开发者,你一定绕不开 Spring—— 它不是简单的工具类,而是统治 Java 企业级开发近 20 年的 “开发圣经”。
很多人学 Spring,只停留在 “会用 @Autowired、@Service” 的层面,面试被问 “Spring IoC 原理”“循环依赖怎么解决”“AOP 底层实现”,瞬间卡壳;开发时遇到 Bean 注入失败、事务不生效,只能瞎猜乱试。
这篇文章,不跳步、不玄学、不堆砌概念,用 “道法术器” 四层逻辑,从 “为什么要有 Spring” 到 “Spring 生态怎么用”,把 Spring 彻底讲透。全程专业准确,新手能入门,老手能查漏补缺,建议立刻收藏,面试、开发、复盘都能直接翻。
想象你是 Java 开发者,要开发一个电商系统,用户下单时需要扣库存、生成订单、发送短信。按传统方式写代码,会陷入 5 个致命坑:
java
运行
public class OrderService {
// 直接new依赖,耦合死死的
private InventoryService inventoryService = new InventoryService();
private SmsService smsService = new SmsService();
public void createOrder(Order order) {
inventoryService.deductStock(order); // 扣库存
// 保存订单到数据库...
smsService.sendNotification(order); // 发短信
}
}
Spring 存在的唯一理由:让开发者只专注核心业务逻辑,把 “对象创建、依赖管理、横切关注点处理” 这些基础设施问题,全部交给框架来做。
“道” 是 Spring 的灵魂,回答 “为什么这么设计”,搞懂这 4 个思想,就抓住了 Spring 的本质。
传统编程:对象自己 “掌控一切”—— 自己创建依赖、自己管理生命周期,比如 “我要用到 A,就自己 new A ()”。
java
运行
A a = new A(); // 我自己创建,自己控制
a.doSomething();
这叫 “正转”—— 控制权在你手里。
控制反转(IoC):把对象的创建、依赖管理权力,从对象本身转移到 Spring 容器。你只管声明 “我需要什么”,容器负责 “给你什么”,不用自己动手 new。
java
运行
@Service // 告诉Spring:我是一个Bean,交给你管理
public class OrderService {
@Autowired // 告诉Spring:我需要一个InventoryService,你给我注入
private InventoryService inventoryService;
}
为什么叫 “反转”?因为控制权从 “开发者 / 对象”,转移到了 “Spring 容器”。
控制反转是 “思想”,依赖注入是 “落地方式”:Spring 容器在创建对象时,自动把依赖的对象 “注入” 到当前对象中,不用你手动赋值。
Spring 支持 3 种注入方式(重点记推荐用法):
日志、事务、安全、缓存这些 “横切关注点”,横切于多个业务模块,若散落在各处,会导致代码重复、维护困难。
AOP 的核心思想:把横切关注点封装成 “切面”,在运行时 “织入” 到业务代码中,不修改业务代码本身,实现 “业务代码和非业务代码分离”。
java
运行
@Transactional // 声明式事务,不用写一行事务管理代码
public void transferMoney(Account from, Account to, BigDecimal amount) {
// 只写核心业务逻辑,事务由Spring自动管理
from.deduct(amount);
to.add(amount);
}
好处:业务代码更纯粹,横切逻辑可复用、可维护。
Spring 的核心理念:你的业务类就是普通的 Java 对象(POJO),不需要继承 Spring 的特定类、实现 Spring 的特定接口。
java
运行
// 普通Java类,没有任何Spring相关代码
public class OrderService {
private InventoryService inventoryService;
// 普通构造器
public OrderService(InventoryService inventoryService) {
this.inventoryService = inventoryService;
}
// 普通业务方法
public void createOrder(Order order) {
inventoryService.deductStock(order);
}
}
这个类可以在 Spring 中使用,也可以单独测试、单独使用,完全不受框架约束 —— 这就是 Spring 的 “非侵入式”,不绑架你的代码。
“法” 是实现 “道” 的路径和方法论,回答 “怎么做”,这 4 个方法论,是 Spring 的核心骨架。
Spring 容器会全程管理 Bean 的生命周期,从创建到销毁,一步不落地:
plaintext
实例化(new对象)→ 属性赋值(注入依赖)→ 初始化(@PostConstruct)→ 使用 → 销毁(@PreDestroy)
关键亮点:Spring 提供多个扩展点,让你可以在生命周期的不同阶段插入自定义逻辑:
Spring 不是 “瞎注入”,而是有一套明确的依赖解析规则:
当 A 依赖 B、B 依赖 A 时(循环依赖),Spring 用 “三级缓存” 完美解决,不用手动处理:
循环依赖解决流程(极简版):
Spring AOP 的底层是 “动态代理”,根据目标对象是否实现接口,选择不同的代理方式:
核心逻辑(伪代码,一看就懂):
java
运行
public class AopProxyFactory {
public Object createProxy(Object target, Advice advice) {
// 目标对象有接口 → JDK动态代理
if (target.getClass().getInterfaces().length > 0) {
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
(proxy, method, args) -> {
advice.before(); // 切面逻辑(比如日志)
Object result = method.invoke(target, args); // 业务逻辑
advice.after(); // 切面逻辑(比如事务提交)
return result;
}
);
} else {
// 目标对象无接口 → CGLIB代理
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback((MethodInterceptor) (obj, method, args, proxy) -> {
advice.before();
Object result = proxy.invokeSuper(obj, args);
advice.after();
return result;
});
return enhancer.create();
}
}
}
Spring 鼓励 “声明式编程”,通过注解或 XML 声明配置,代替硬编码,让代码更简洁、可维护。
java
运行
// 声明配置类
@Configuration // 告诉Spring:这是一个配置类
@ComponentScan("com.example") // 声明扫描哪些包的Bean
public class AppConfig {
@Bean // 声明一个Bean,交给Spring管理
public DataSource dataSource() {
return new HikariDataSource();
}
}
// 声明Service Bean + 事务
@Service // 声明这是一个Service层Bean
@Transactional // 声明该类所有方法都需要事务管理
public class UserService {
// 只写业务逻辑,配置由Spring管理
}
声明式编程的好处:关注点分离(业务归业务,配置归配置)、可维护性强、修改配置不用改业务代码。
“术” 是具体的技术技巧,回答 “用什么工具实现”,掌握这些,遇到 Spring 相关问题能快速定位、解决。
Spring 容器(ApplicationContext)的启动是一个精密的流程,掌握它,能轻松排查 “容器启动失败” 问题:
java
运行
// 构造器注入
public OrderService(InventoryService inventoryService) {
this.inventoryService = inventoryService;
}
底层原理:Spring 通过反射找到该构造器,从容器中获取 InventoryService 实例,传入构造器创建 OrderService。
java
运行
@Autowired
private InventoryService inventoryService;
底层原理:Spring 通过反射获取该私有字段,设置 setAccessible (true)(突破私有访问限制),直接将容器中的 Bean 赋值给字段。
Spring AOP 使用 AspectJ 的切点表达式,常用 3 种表达式,直接复制可用:
java
运行
@Aspect
@Component
public class LoggingAspect {
// 1. execution表达式:匹配指定包下的所有方法(最常用)
@Before("execution(* com.example.service.*.*(..))")
public void logBefore() {
System.out.println("方法执行前,打印日志");
}
// 2. @annotation表达式:匹配有特定注解的方法
@Around("@annotation(com.example.annotation.Loggable)")
public Object logAround(ProceedingJoinPoint pjp) throws Throwable {
long start = System.currentTimeMillis();
Object result = pjp.proceed(); // 执行原方法
long duration = System.currentTimeMillis() - start;
System.out.println("方法执行耗时:" + duration + "ms");
return result;
}
// 3. within表达式:匹配指定包及子包下的所有方法
@AfterReturning("within(com.example.controller..*)")
public void logAfterReturning() {
System.out.println("方法正常返回,打印日志");
}
}
Spring 事务的核心是 @Transactional 注解和 TransactionInterceptor(事务拦截器),底层流程如下:
常用 @Transactional 属性(开发必记):
java
运行
@Transactional(
propagation = Propagation.REQUIRED, // 事务传播行为(默认,有事务则加入,无则新建)
isolation = Isolation.READ_COMMITTED, // 隔离级别(默认,避免脏读)
timeout = 30, // 超时时间(30秒,超时回滚)
rollbackFor = RuntimeException.class // 哪些异常触发回滚(默认只回滚运行时异常)
)
“器” 是 Spring 的具体工具和组件,回答 “有哪些东西可以用”,Spring 生态极其完善,开箱即用,覆盖开发全场景。
表格
| 模块 | 核心功能 | 核心类 / 接口 |
|---|---|---|
| spring-core | IoC 容器基础,提供核心工具类 | BeanFactory, ApplicationContext |
| spring-beans | Bean 的创建、管理、依赖注入 | BeanDefinition, BeanWrapper |
| spring-aop | 面向切面编程,提供 AOP 实现 | ProxyFactory, AspectJProxyFactory |
| spring-context | 容器上下文、事件机制、资源管理 | ApplicationEvent, ResourceLoader |
| spring-tx | 事务管理,支持声明式 / 编程式事务 | PlatformTransactionManager, @Transactional |
| spring-web | Web 开发基础,整合 Servlet | DispatcherServlet, HandlerMapping |
| spring-webmvc | Spring MVC 实现,用于 Web 开发 | @Controller, @RequestMapping |
| spring-jdbc | JDBC 抽象,简化数据库操作 | JdbcTemplate, NamedParameterJdbcTemplate |
Spring Boot 的核心是 “自动配置”,解决了 Spring “配置繁琐” 的痛点,只需一个注解,就能快速启动 Spring 应用:
java
运行
@SpringBootApplication // 组合注解:@Configuration + @EnableAutoConfiguration + @ComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args); // 一键启动
}
}
自动配置原理:
Spring Cloud 基于 Spring Boot,提供微服务开发的全套组件,解决微服务中的服务发现、网关、链路追踪等问题:
表格
| 组件 | 核心功能 |
|---|---|
| Spring Cloud Config | 分布式配置中心,统一管理配置 |
| Spring Cloud Netflix | 服务发现(Eureka)、断路器(Hystrix) |
| Spring Cloud Gateway | API 网关,统一入口、路由转发 |
| Spring Cloud Sleuth | 链路追踪,排查微服务调用问题 |
| Spring Cloud Stream | 消息驱动,简化消息队列使用 |
Spring Data 统一了各类数据访问框架的 API,只需定义接口,Spring 自动实现 CRUD 方法,不用写 SQL:
java
运行
// 继承JpaRepository,自动获得CRUD、分页、排序等方法
public interface UserRepository extends JpaRepository<User, Long> {
// 方法名解析为SQL:SELECT * FROM user WHERE last_name = ?
List<User> findByLastName(String lastName);
// 自定义JPQL查询
@Query("SELECT u FROM User u WHERE u.email = ?1")
User findByEmail(String email);
}
Spring Security 提供身份认证、授权、防攻击等功能,快速实现系统安全:
java
运行
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/public/**").permitAll() // 公开接口,无需登录
.antMatchers("/admin/**").hasRole("ADMIN") // 管理员才能访问
.anyRequest().authenticated() // 其他接口需登录
.and()
.formLogin()
.loginPage("/login") // 自定义登录页
.permitAll();
}
}
很多人觉得 Spring 复杂,其实用 “一家大型餐厅” 的比喻,就能轻松理解道法术器四层逻辑:
用第一性原理来看,Spring 的本质是:一个通过 IoC 容器和 AOP 机制,实现 Java 应用松耦合、可测试、易维护的企业级应用开发框架。
它的核心哲学,就是 “道法术器” 四层体系:
这就是 Spring 能统治 Java 近 20 年的根本原因:它不仅是一个框架,更是一套完整的思想体系和开发方法论。
表格
| 层次 | 核心内容 | 一句话总结 |
|---|---|---|
| 道 | IoC、DI、AOP、非侵入式 | 把控制权交出去,只专注核心业务 |
| 法 | 生命周期、依赖解析、代理机制、声明式编程 | 规范对象管理和依赖注入的流程 |
| 术 | 启动流程、注入技巧、AOP 表达式、事务拦截 | 解决 Spring 开发中的具体技术问题 |
| 器 | Spring Boot、Cloud、Data、Security | 开箱即用的生态工具,提升开发效率 |
学 Spring 时,你最头疼的问题是什么?
评论区留下你的痛点,我会挑高频问题,下期专门出《Spring 常见坑排查实战》,手把手教你解决,还会附赠 Spring 面试高频题合集!