使用没有类型的 args 指示符创建切入点会导致 BeanCurrentlyInCreationException
Creating A pointcut using args designator with no types results in BeanCurrentlyInCreationException
使用 Spring AOP
,当尝试使用指示符 args
创建 Pointcut
而未提供任何类型时,会导致一系列以 BeanCurrentlyInCreationException
[= 开头的异常17=]
例子
object _001_Spring_AOP_Pointcut_Args_NoArgs {
open class BeanA {
open fun m() {
println("BeanA#m()")
}
}
@Aspect
class AspectA {
@Pointcut("args()")
private fun pc_noArgs() = Unit
@After("sero4.spring.z_added._001_Spring_AOP_Pointcut_Args_NoArgs.AspectA.pc_noArgs()")
private fun ac_noArgs() = println("ac_noArgs")
}
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
open class Config {
@Bean
open fun beanA(): BeanA = BeanA()
@Bean
open fun aspectA(): AspectA = AspectA()
}
fun runJava() {
AnnotationConfigApplicationContext(Config::class.java)
}
}
运行 方法
@Test
fun test_run() {
_001_Spring_AOP_Pointcut_Args_NoArgs.runJava()
}
异常总结
Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'beanA' defined in sero4.spring.z_added._001_Spring_AOP_Pointcut_Args_NoArgs$Config: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [sero4.spring.z_added._001_Spring_AOP_Pointcut_Args_NoArgs$BeanA]: Factory method 'beanA' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'aspectA' defined in sero4.spring.z_added._001_Spring_AOP_Pointcut_Args_NoArgs$Config: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [sero4.spring.z_added._001_Spring_AOP_Pointcut_Args_NoArgs$AspectA]: Factory method 'aspectA' threw exception; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'aspectA': Requested bean is currently in creation: Is there an unresolvable circular reference?
args()
对比 execution(* *())
这是拦截所有无参数方法的不寻常方式。我宁愿让它更明确,而是使用 execution(* *())
。如果您曾经从 Spring AOP 迁移到 AspectJ,您会注意到 args()
匹配那里的所有类型的切入点,例如call
、initialization
、preinitialization
、staticinitialization
、get
和不带参数的构造函数 calls/executions。
切入点作用域
在 Spring AOP 中,您的问题可能是另一个问题:您的切入点太宽泛了。它匹配 Spring beans 中的许多连接点,也在 Spring 或第三方 classes 本身中。所以你想限制切入点的范围,例如像
execution(* *()) && within(my.own.package.**)
何时(不)在切入点中使用完全限定的 class 名称
顺便说一句,如果你的切入点定义在与使用它的建议完全相同的 class 中,则没有必要使用完全限定的 class 名称,即而不是
@After("sero4.spring.z_added._001_Spring_AOP_Pointcut_Args_NoArgs.AspectA.pc_noArgs()")
你可以使用
@After("pc_noArgs()")
内联切入点
如果您不打算在其他建议中重复使用相同的切入点,只需删除 @Pointcut
并定义一个内联切入点,例如
@After("execution(* *()) && within(my.own.package.**)")
建议应该是public
虽然可以将 @Pointcut
方法定义为私有方法,但如果您不从其他 classes 引用它,@After
建议应该是 public .它可能适用于 Spring AOP,但违反约定。同样,如果您曾经迁移到 AspectJ,您甚至会遇到编译错误,因为 AspectJ 通知必须是 public.
代码共享失败,出现以下异常 -
org.springframework.beans.factory.BeanCurrentlyInCreationException
,当 pointcut
表达式在包内有范围时,方面 class 所在。
示例:
bean 的完全限定名称:
rg.spring.boot.AspectA
rg.spring.boot.bean.BeanA
像下面这样的切入点表达式将失败:
@Pointcut("args() && within(rg.spring.boot..*)")
然而,以下切入点表达式成功:
@Pointcut("args() && within(rg.spring.boot.bean..*)")
这个例外,per 我,是因为 pointcut
在初始化期间以方面的框架方法为目标。要解决异常,您可以将 bean 移动到特定包并微调该包的 pointcut
表达式的范围。
使用 Spring AOP
,当尝试使用指示符 args
创建 Pointcut
而未提供任何类型时,会导致一系列以 BeanCurrentlyInCreationException
[= 开头的异常17=]
例子
object _001_Spring_AOP_Pointcut_Args_NoArgs {
open class BeanA {
open fun m() {
println("BeanA#m()")
}
}
@Aspect
class AspectA {
@Pointcut("args()")
private fun pc_noArgs() = Unit
@After("sero4.spring.z_added._001_Spring_AOP_Pointcut_Args_NoArgs.AspectA.pc_noArgs()")
private fun ac_noArgs() = println("ac_noArgs")
}
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
open class Config {
@Bean
open fun beanA(): BeanA = BeanA()
@Bean
open fun aspectA(): AspectA = AspectA()
}
fun runJava() {
AnnotationConfigApplicationContext(Config::class.java)
}
}
运行 方法
@Test
fun test_run() {
_001_Spring_AOP_Pointcut_Args_NoArgs.runJava()
}
异常总结
Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'beanA' defined in sero4.spring.z_added._001_Spring_AOP_Pointcut_Args_NoArgs$Config: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [sero4.spring.z_added._001_Spring_AOP_Pointcut_Args_NoArgs$BeanA]: Factory method 'beanA' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'aspectA' defined in sero4.spring.z_added._001_Spring_AOP_Pointcut_Args_NoArgs$Config: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [sero4.spring.z_added._001_Spring_AOP_Pointcut_Args_NoArgs$AspectA]: Factory method 'aspectA' threw exception; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'aspectA': Requested bean is currently in creation: Is there an unresolvable circular reference?
args()
对比 execution(* *())
这是拦截所有无参数方法的不寻常方式。我宁愿让它更明确,而是使用 execution(* *())
。如果您曾经从 Spring AOP 迁移到 AspectJ,您会注意到 args()
匹配那里的所有类型的切入点,例如call
、initialization
、preinitialization
、staticinitialization
、get
和不带参数的构造函数 calls/executions。
切入点作用域
在 Spring AOP 中,您的问题可能是另一个问题:您的切入点太宽泛了。它匹配 Spring beans 中的许多连接点,也在 Spring 或第三方 classes 本身中。所以你想限制切入点的范围,例如像
execution(* *()) && within(my.own.package.**)
何时(不)在切入点中使用完全限定的 class 名称
顺便说一句,如果你的切入点定义在与使用它的建议完全相同的 class 中,则没有必要使用完全限定的 class 名称,即而不是
@After("sero4.spring.z_added._001_Spring_AOP_Pointcut_Args_NoArgs.AspectA.pc_noArgs()")
你可以使用
@After("pc_noArgs()")
内联切入点
如果您不打算在其他建议中重复使用相同的切入点,只需删除 @Pointcut
并定义一个内联切入点,例如
@After("execution(* *()) && within(my.own.package.**)")
建议应该是public
虽然可以将 @Pointcut
方法定义为私有方法,但如果您不从其他 classes 引用它,@After
建议应该是 public .它可能适用于 Spring AOP,但违反约定。同样,如果您曾经迁移到 AspectJ,您甚至会遇到编译错误,因为 AspectJ 通知必须是 public.
代码共享失败,出现以下异常 -
org.springframework.beans.factory.BeanCurrentlyInCreationException
,当 pointcut
表达式在包内有范围时,方面 class 所在。
示例:
bean 的完全限定名称:
rg.spring.boot.AspectA
rg.spring.boot.bean.BeanA
像下面这样的切入点表达式将失败:
@Pointcut("args() && within(rg.spring.boot..*)")
然而,以下切入点表达式成功:
@Pointcut("args() && within(rg.spring.boot.bean..*)")
这个例外,per 我,是因为 pointcut
在初始化期间以方面的框架方法为目标。要解决异常,您可以将 bean 移动到特定包并微调该包的 pointcut
表达式的范围。