Spring Boot注解
- [Spring Boot 注解是如何工作的?(理解 AOP 的前置知识)](#Spring Boot 注解是如何工作的?(理解 AOP 的前置知识))
-
- [一、Spring 到底在干什么?一句话版本](#一、Spring 到底在干什么?一句话版本)
- [二、为什么 @Service 的类不用 new?](#二、为什么 @Service 的类不用 new?)
-
- [1️⃣ 一个最简单的 Spring Boot 程序](#1️⃣ 一个最简单的 Spring Boot 程序)
- [三、@Service / @Component 是干嘛的?](#三、@Service / @Component 是干嘛的?)
- [四、@Autowired 是怎么注入的?](#四、@Autowired 是怎么注入的?)
- [五、Spring 启动时的"对象生命周期"(非常关键)](#五、Spring 启动时的“对象生命周期”(非常关键))
- [六、AOP 的注解是从什么时候开始生效的?](#六、AOP 的注解是从什么时候开始生效的?)
- 七、真相:代理对象在「启动阶段」就创建好了
- [八、这也是为什么 AOP 不会对 this.xxx() 生效](#八、这也是为什么 AOP 不会对 this.xxx() 生效)
- [九、@Aspect 本质上是什么?](#九、@Aspect 本质上是什么?)
- [十、@Before / @AfterReturning 是怎么用到的?](#十、@Before / @AfterReturning 是怎么用到的?)
- 十一、总结一条完整因果链(非常重要)
- [十二、所以 AOP "自动代理"并不神秘](#十二、所以 AOP “自动代理”并不神秘)
- 十三、给读者的最终认知模型(建议放在文章结尾)
- 结语
Spring Boot 注解是如何工作的?(理解 AOP 的前置知识)
很多初学者在学 Spring Boot 和 AOP 时,都会有类似的疑惑:
java
@Service
public class UserService {
}
❓ 我没有 new,它怎么就能用?
❓ 加个
@Aspect,怎么方法就被"代理"了?❓ Spring 到底在启动时做了什么?
这篇文章,我们不讲源码细节 ,而是用通俗 + 可运行的代码,把 Spring 注解背后的机制讲清楚。
一、Spring 到底在干什么?一句话版本
Spring 的核心工作只有一件事:
扫描类 → 创建对象 → 管理对象 → 在合适的时机"加工"对象
AOP、事务、依赖注入,本质都是这条流水线上的不同"加工步骤"。
二、为什么 @Service 的类不用 new?
1️⃣ 一个最简单的 Spring Boot 程序
java
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
当你运行这行代码时,Spring 会:
- 启动容器(ApplicationContext)
- 扫描 classpath
- 找出"需要交给 Spring 管理的类"
三、@Service / @Component 是干嘛的?
java
@Service
public class UserService {
public void register() {
System.out.println("注册用户");
}
}
这行 @Service 的真实含义是:
"请 Spring 在启动时,帮我创建这个类的对象,并放进容器里。"
本质效果等价于(伪代码):
java
UserService userService = new UserService();
springContainer.put("userService", userService);
👉 你没 new,但 Spring new 了
四、@Autowired 是怎么注入的?
java
@RestController
public class UserController {
@Autowired
private UserService userService;
}
Spring 在启动时会:
- 创建
UserController - 发现字段上有
@Autowired - 去容器里找
UserService - 通过反射赋值
java
userController.userService = springContainer.get(UserService.class);
👉 这一步仍然是反射 + 容器
五、Spring 启动时的"对象生命周期"(非常关键)
简化版流程如下:
text
扫描类
↓
解析注解(@Component、@Service、@Aspect...)
↓
创建 Bean 对象
↓
Bean 后处理(BeanPostProcessor)
↓
放入容器
⚠️ AOP 就是在"Bean 后处理"阶段介入的
六、AOP 的注解是从什么时候开始生效的?
我们先看一个切面:
java
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.UserService.*(..))")
public void before() {
System.out.println("记录日志");
}
}
很多人会误以为:
❌ Spring 在调用方法时"突然拦截了"
这是错的。
七、真相:代理对象在「启动阶段」就创建好了
当 Spring 启动时:
- 发现
UserService是一个 Bean - 发现有
@Aspect - 发现切点匹配
UserService - Spring 决定:这个 Bean 需要被代理
于是它不会直接放入原始对象,而是:
text
UserService 原始对象
↓
Spring AOP
↓
代理对象(JDK / CGLIB)
↓
放入容器
👉 容器里从一开始拿到的,就是代理对象
八、这也是为什么 AOP 不会对 this.xxx() 生效
java
@Service
public class UserService {
public void a() {
this.b(); // ❌ 不走代理
}
public void b() {
System.out.println("b");
}
}
原因很简单:
this指的是 当前对象内部- 不是 Spring 容器里的 代理对象
👉 AOP 是通过"代理对象"生效的,不是魔法
九、@Aspect 本质上是什么?
java
@Aspect
@Component
public class LoggingAspect {
}
拆开看:
-
@Component:让 Spring 管理这个类 -
@Aspect:告诉 Spring ------"这个 Bean 不普通,它是用来生成代理规则的"
Spring 会把它交给 AOP 解析器处理。
十、@Before / @AfterReturning 是怎么用到的?
java
@Before("execution(* com.example.UserService.*(..))")
public void before() {}
Spring 会在启动时:
- 解析表达式
- 建立「方法 → 增强逻辑」的映射关系
- 生成代理类时,把这些逻辑织入进去
👉 不是运行时临时判断,而是提前准备好的
十一、总结一条完整因果链(非常重要)
text
@SpringBootApplication
↓
Spring 启动
↓
扫描 @Component / @Service / @Aspect
↓
创建 Bean
↓
AOP 判断是否需要代理
↓
生成代理对象
↓
放入容器
↓
你 @Autowired 拿到的是代理对象
十二、所以 AOP "自动代理"并不神秘
你现在应该能理解这句话了:
AOP 之所以能"自动生效",
是因为 Spring 在启动阶段就已经替你生成了代理对象。
十三、给读者的最终认知模型(建议放在文章结尾)
- Spring 注解 ≠ 魔法
- 注解 = "规则声明"
- Spring = 规则执行者
- AOP = Spring 在创建 Bean 时顺手做的"代理加工"
结语
当你理解了:
- Spring 是"容器"
- 注解是"标记"
- AOP 是"Bean 创建阶段的加工逻辑"
你再回头看 @Aspect、@Before,只会觉得:
哦,原来如此。