使用args指示符创建切入点(不带类型)会导致beancurrentlyincreationexception

1mrurvl1  于 2021-07-26  发布在  Java
关注(0)|答案(2)|浏览(345)

使用 Spring AOP ,尝试创建 Pointcut 使用指示符 args 虽然不提供任何类型,但会导致一系列异常,从 BeanCurrentlyInCreationException 例子

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)
    }

}

run方法

@Test
    fun test_run() {
        _001_Spring_AOP_Pointcut_Args_NoArgs.runJava()
    }

异常摘要
在上下文初始化过程中遇到异常-取消刷新尝试:org.springframework.beans.factory.beancreationexception:创建名为'beana'的bean时出错,该bean在sero4.spring.z中定义。\u 001\u spring\u aop\u pointcut\u args\u noargs$config:通过工厂方法示例化bean失败;嵌套异常为org.springframework.beans.beaninstantiationexception:未能示例化[sero4.spring.z\u added.\u 001\u spring\u aop\u pointcut\u args\u noargs$beana]:工厂方法“beana”引发异常;嵌套的异常是org.springframework.beans.factory.beancreationexception:创建名为'aspecta'的bean时出错,该bean在sero4.spring.z中定义。\u 001\u spring\u aop\u pointcut\u args\u noargs$config:通过工厂方法示例化bean失败;嵌套异常为org.springframework.beans.beaninstantiationexception:未能示例化[sero4.spring.z\u added.\u 001\u spring\u aop\u pointcut\u args\u noargs$aspecta]:工厂方法“aspecta”引发异常;嵌套异常为org.springframework.beans.factory.beancurrentlyincreationexception:创建名为“aspecta”的bean时出错:请求的bean当前正在创建中:是否存在无法解析的循环引用?

sigwle7e

sigwle7e1#

args()与执行(**())

这是一种不寻常的拦截所有没有参数的方法的方式。我宁愿把它说得更清楚,更实用 execution(* *()) 相反。如果您曾经从springaop迁移到aspectj,您会注意到 args() 匹配所有类型的切入点,例如。 call , initialization , preinitialization , staticinitialization , get 构造函数调用/执行,而不带参数。

切入点范围

不过,在 Spring aop中,你的问题可能是另一个:你的切入点太宽了。它匹配springbean中的许多连接点,也匹配spring或第三方类本身。所以你想限制切入点的范围,例如

execution(* *()) && within(my.own.package.**)

何时(不)在切入点中使用完全限定类名

顺便说一句,如果切入点与使用它的通知定义在同一个类中,则不必使用完全限定的类名,即,而不是

@After("sero4.spring.z_added._001_Spring_AOP_Pointcut_Args_NoArgs.AspectA.pc_noArgs()")

你可以用

@After("pc_noArgs()")

内联切入点

如果你不打算在其他建议中重复使用相同的切入点,那就放弃它吧 @Pointcut 并定义一个内联切入点,例如

@After("execution(* *()) && within(my.own.package.**)")

建议应该是公开的

虽然可以定义 @Pointcut 方法作为私有的,如果不从其他类引用它,则 @After 建议应该是公开的。它可能在SpringAOP中起作用,但与约定背道而驰。同样,如果迁移到aspectj,甚至会出现编译错误,因为aspectj建议必须是公共的。

ttygqcqt

ttygqcqt2#

共享的代码失败,出现以下异常-

org.springframework.beans.factory.BeanCurrentlyInCreationException

,当 pointcut 表达式在方面类所在的包中有一个作用域。
例子:
bean的完全限定名:

rg.spring.boot.AspectA

rg.spring.boot.bean.BeanA

像下面这样的切入点表达式将失败:

@Pointcut("args() && within(rg.spring.boot..*)")

然而,以下切入点表达式成功:

@Pointcut("args() && within(rg.spring.boot.bean..*)")

在我看来,例外是因为 pointcut 在初始化期间针对方面的框架方法。要解决异常,可以将bean移动到特定的包中,并微调 pointcut 那个包裹的表达式。

相关问题