针对这个问题,我们可以从“时间点 (When)”和“代码位置 (Where)”两个维度来回答。
时间点 (When): 在 Bean 的生命周期中的“初始化”阶段
Spring AOP 的代理创建过程,深深地嵌入在 Spring Bean 的生命周期中。一个 Bean 的生命周期大致如下:
- 实例化 (Instantiation): Spring 通过反射创建出 Bean 的一个空对象。
- 属性填充 (Populate Properties): Spring 进行依赖注入,将
@Autowired等注解标记的依赖设置到 Bean 对象中。 - 初始化 (Initialization): 这是一个关键阶段,包含多个步骤。
- 执行
Aware接口相关的方法(如BeanNameAware)。 - 执行
BeanPostProcessor的postProcessBeforeInitialization方法。 - 执行
@PostConstruct或init-method指定的初始化方法。 - 执行
BeanPostProcessor的postProcessAfterInitialization方法。 <-- 就是在这里!
- 执行
- 就绪状态 (Ready): Bean 创建完成,放入单例池,可供其他组件使用。
结论: Spring 是在 Bean 完成实例化和属性填充,并且执行完它自身的初始化逻辑之后,通过一个名为 BeanPostProcessor 的钩子来创建代理对象的。
为什么是这个时间点?
因为在这个时间点,原始的目标 Bean 已经是一个完整、可用的对象了。它的所有依赖都已注入,所有初始化配置都已完成。这时对它进行“包装”(创建代理)是最安全、最合适的时机。
代码位置 (Where): 在 BeanPostProcessor 的实现类中
现在我们知道了“时间点”,那么具体是哪段代码在工作呢?
核心角色:BeanPostProcessor
你可以把 BeanPostProcessor 想象成一个 Bean 的“质量检验站”。每个 Bean 在最终“出厂”(放入容器)前,都必须经过这个检验站。检验站可以决定是直接放行这个 Bean,还是对它进行一番“包装和改造”再放行。
具体实现类:AnnotationAwareAspectJAutoProxyCreator
-
AOP 的总开关:当我们使用
@EnableAspectJAutoProxy注解时,Spring 会向容器中注册一个名为AnnotationAwareAspectJAutoProxyCreator的 Bean。 -
AOP 的总指挥:这个类就是 AOP 功能的总指挥。它本身就是一个
BeanPostProcessor的实现。 -
关键的拦截方法:
AnnotationAwareAspectJAutoProxyCreator继承了AbstractAutoProxyCreator,其中最核心的方法是postProcessAfterInitialization()。
详细的代码执行路径:
-
当一个 Bean(比如你的
UserService)走到了生命周期的第 3 步(初始化之后),Spring 容器会调用AnnotationAwareAspectJAutoProxyCreator的postProcessAfterInitialization(Object bean, String beanName)方法。 -
这个方法内部会调用一个核心的包装方法
wrapIfNecessary(bean, beanName, cacheKey)。这个方法的名字已经说明了一切:“如果需要,就包装它”。 -
在
wrapIfNecessary方法中,它会执行以下关键操作:
a. 寻找适用的切面 (Find Advisors):它会调用getAdvicesAndAdvisorsForBean()方法,扫描容器中所有的@Aspect切面,解析它们的@Pointcut表达式,看看有没有哪个切点的规则能匹配上当前这个UserServiceBean 的方法。
b. 决策 (Decision):
* 如果没有找到任何可以应用的切面,说明这个 Bean 不需要 AOP 增强。wrapIfNecessary方法会直接返回原始的UserService对象。
* 如果找到了一个或多个适用的切面,说明这个 Bean 需要被代理。c. 创建代理 (Create Proxy):程序会继续执行
createProxy()方法。这个方法会:
* 创建一个ProxyFactory(代理工厂)。
* 将原始的UserService对象(作为target)、所有找到的切面逻辑(Advisors)都设置到工厂里。
* 由工厂决定使用 JDK 动态代理还是 CGLIB 来生成最终的代理对象。 -
返回代理对象:最终,
postProcessAfterInitialization方法会返回这个新创建的代理对象。Spring 容器会用这个代理对象替换掉单例池中原始的UserService对象。
图解流程
+--------------------------------+
| Spring Container |
| (Starts creating UserService) |
+--------------------------------+
|
v
+--------------------------------+
| 1. Instantiate UserService |
+--------------------------------+
|
v
+--------------------------------+
| 2. Populate Properties (DI) |
+--------------------------------+
|
v
+--------------------------------+
| 3. Initialize (@PostConstruct) |
+--------------------------------+
|
v
+-----------------------------------------------------------------+
| 4. BeanPostProcessor (AnnotationAwareAspectJAutoProxyCreator) |
| - postProcessAfterInitialization(userService, "userService") |
| | |
| +--> wrapIfNecessary() |
| | |
| +--> Does any @Pointcut match UserService? |
| | | |
| (No)| | (Yes) |
| v v |
| Return original bean createProxy() -> [UserServiceProxy]|
| | |
| <------------------------+---------------------------------+
| |
+-----------------------------------------------------------------+
| (Returns either original bean or proxy)
v
+--------------------------------+
| 5. UserService (or its Proxy) |
| is now ready in the container |
+--------------------------------+
总结
- When (时间点): 在 Bean 生命周期的初始化阶段之后,通过
BeanPostProcessor的postProcessAfterInitialization方法。 - Where (代码位置): 在
AnnotationAwareAspectJAutoProxyCreator类(由@EnableAspectJAutoProxy注册)的wrapIfNecessary方法中,该方法会判断是否需要创建代理,并在需要时调用createProxy方法来完成创建。
所以,任何脱离了 Spring Bean 生命周期管理的操作(比如手动 new 一个对象),都无法享受到 AOP 的增强,因为它们从未经过这个重要的“质量检验站”。
895

被折叠的 条评论
为什么被折叠?



