内容提要
本文讨论了如何通过自定义 Spring Bean 的名称来避免被代理。具体而言,使用完整类名加上“.ORIGINAL”后缀命名的 Bean 将不会被 AOP 代理。文章分析了 Spring 中 BeanPostProcessor 的工作原理,特别是如何判断一个 Bean 是否需要代理,从而帮助读者深入理解 Spring AOP 的机制。
延伸解读
命名规则的实际影响
将Bean命名为“完整类名+.ORIGINAL”后,即使该类位于切点表达式范围内,Spring也不会为其创建代理。这意味着所有AOP增强(如@Before、@After等)都不会生效,方法调用将直接执行原始对象。因此,若你希望某个Bean完全避开AOP,可以采用此命名方式,但需注意这会使该Bean失去所有切面功能。
与常规代理机制的对比
通常,Spring通过BeanPostProcessor在Bean初始化后决定是否代理,而InstantiationAwareBeanPostProcessor允许在实例化前提前返回代理。但“ORIGINAL”命名触发的是shouldSkip逻辑,使Bean在实例化前就被标记为无需代理,从而跳过后续代理创建。这与普通Bean的代理流程形成对比,提供了一种更早的干预手段。
使用时的注意事项
该特性自Spring 5.1引入,依赖AutoProxyUtils.isOriginalInstance方法判断。使用时必须确保Bean名称严格等于“完整类名+.ORIGINAL”,且类名大小写敏感。此外,该方式仅适用于自动代理创建器(如AbstractAutoProxyCreator),若使用其他代理机制(如手动ProxyFactory)则可能无效。
Q&A
如何通过 Spring Bean 的名称避免被 AOP 代理?
可以通过使用完整类名加上 '.ORIGINAL' 后缀来命名 Bean,这样该 Bean 就不会被 AOP 代理。
Spring 5.1 引入了什么新的 Bean 命名规则?
Spring 5.1 引入了使用完整类名加上 '.ORIGINAL' 后缀的命名规则,允许开发者控制 Bean 是否被代理。
BeanPostProcessor 在 Spring 中的作用是什么?
BeanPostProcessor 在 Bean 实例化之前进行预处理,决定是否创建代理对象。
shouldSkip 方法在 Bean 代理判断中起什么作用?
shouldSkip 方法用于判断 Bean 是否需要代理,依据是 Bean 名称是否符合特定格式。
如何判断一个 Bean 是否是原始实例?
通过检查 Bean 名称是否按照类名的完整路径加上 '.ORIGINAL' 的方式命名来判断。
Spring AOP 的代理机制是如何工作的?
Spring AOP 通过 BeanPostProcessor 在 Bean 实例化之前检查是否需要创建代理,如果 Bean 名称符合特定格式,则不创建代理。