Java AOP切入点未注册

Java AOP切入点未注册,java,spring,aop,Java,Spring,Aop,我有一个带有3个方法的Springbean,a、B和C。methodA是入口点,它调用methodB,该方法调用methodC 这是我的豆子: <bean id="myBean" class="misc.zombies.Braainns" scope="prototype"> 这个切入点不起作用,建议永远不会应用 <aop:config> <aop:aspect id="deadLockRetry" ref="myDeadLockRetryExecutor

我有一个带有3个方法的Springbean,a、B和C。methodA是入口点,它调用methodB,该方法调用methodC

这是我的豆子:

<bean id="myBean" class="misc.zombies.Braainns" scope="prototype">
这个切入点不起作用,建议永远不会应用

<aop:config>
    <aop:aspect id="deadLockRetry" ref="myDeadLockRetryExecutor">
        <aop:pointcut id="myRetryOperation" expression="execution(* misc.zombies.Braaainns.methodC(..))"/>
        <aop:around pointcut-ref="myRetryOperation" method="retry"/>    
    </aop:aspect>
</aop:config>

这个切入点确实有效,但建议仅适用于方法A

<aop:config>
    <aop:aspect id="deadLockRetry" ref="myDeadLockRetryExecutor">
        <aop:pointcut id="myRetryOperation" expression="execution(* misc.zombies.Braaainns.*(..))"/>
        <aop:around pointcut-ref="myRetryOperation" method="retry"/>    
    </aop:aspect>
</aop:config>

我认为Spring AOP切入点需要在接口上声明,而不是在具体的类上声明,因为它们是基于代理的

与AspectJ不同,Spring AOP不会将任何特殊的东西编译到您的代码中——相反,它为与
myBean
bean连接的任何bean提供一个代理对象,以便在其他类调用
methodC()
时可以运行给定的建议

从同一类中调用建议的方法不会像您希望的那样工作,因为此时,
methodB()
正在同一类中调用
methodC()
,而不是在代理对象上

:

SpringAOP默认使用标准J2SE动态代理作为AOP代理。这允许代理任何接口(或接口集)

另请参见“了解更多信息”一节


如果您真的希望建议如您在问题中所概述的那样发挥作用,那么听起来您可能可以替代默认机制,尽管为了简单起见,我建议使用纯接口代理-建议附在您的接口边界上。

我相信Spring AOP切入点需要在接口上声明,不是具体的类,因为它们是基于代理的

与AspectJ不同,Spring AOP不会将任何特殊的东西编译到您的代码中——相反,它为与
myBean
bean连接的任何bean提供一个代理对象,以便在其他类调用
methodC()
时可以运行给定的建议

从同一类中调用建议的方法不会像您希望的那样工作,因为此时,
methodB()
正在同一类中调用
methodC()
,而不是在代理对象上

:

SpringAOP默认使用标准J2SE动态代理作为AOP代理。这允许代理任何接口(或接口集)

另请参见“了解更多信息”一节


如果你真的想让建议如你在问题中所概述的那样发挥作用,那么听起来你可能可以替代默认机制,尽管为了简单起见,我建议使用纯接口代理——建议附在你的接口边界上。

Spring AOP在你的bean周围创建代理,因此对于每个方法methoda、methodb,methodc,在你的bean周围的代理上存在methoda2、methodb2、methodc2

现在我们从外部调用
bean.methodA()
,客户机实际看到的是代理,因此调用了
proxy.methods2()
,它委托给
bean.methodA()
。现在,如果
bean.methodA()
调用
bean.methodB()
,则永远不会调用代理逻辑,因为上下文已经在代理中:

proxy             bean  
methodA2() -->    methodA()
                   |
                   V  
methodB2() -->    methodB()
但这正是你想要的:

proxy             bean  
methodA2() -->    methodA()
                     |
   /-----------------/
   |                 
   V
methodB2() -->    methodB()
有几种方法可以解决此问题:

  • 到目前为止,最好的方法是以以下方式更改您的设计:

    • methodA()根本不调用methodB()

    • methodA()和methodB()位于不同的benas中,其中一个被注入到另一个benas中

    • methodA()周围的代理逻辑对于这两种方法都足够了

  • 如果不可能,您可以选择使用AspectJ编译(请参阅)。这样,您就不再使用代理,而是将方面编织到您的类中

  • 或者通过使bean对象知道其周围的代理来违反AOP原则:

    public void methodA(){
        ((MyInterface)AopContext.currentProxy()).methodB();
    }
    

  • SpringAOP在您的bean周围创建代理,因此对于每个方法methoda、methodb、methodc,在您的bean周围的代理上都存在一个方法methoda2、methodb2、methodc2

    现在我们从外部调用
    bean.methodA()
    ,客户机实际看到的是代理,因此调用了
    proxy.methods2()
    ,它委托给
    bean.methodA()
    。现在,如果
    bean.methodA()
    调用
    bean.methodB()
    ,则永远不会调用代理逻辑,因为上下文已经在代理中:

    proxy             bean  
    methodA2() -->    methodA()
                       |
                       V  
    methodB2() -->    methodB()
    
    但这正是你想要的:

    proxy             bean  
    methodA2() -->    methodA()
                         |
       /-----------------/
       |                 
       V
    methodB2() -->    methodB()
    
    有几种方法可以解决此问题:

  • 到目前为止,最好的方法是以以下方式更改您的设计:

    • methodA()根本不调用methodB()

    • methodA()和methodB()位于不同的benas中,其中一个被注入到另一个benas中

    • methodA()周围的代理逻辑对于这两种方法都足够了

  • 如果不可能,您可以选择使用AspectJ编译(请参阅)。这样,您就不再使用代理,而是将方面编织到您的类中

  • 或者通过使bean对象知道其周围的代理来违反AOP原则:

    public void methodA(){
        ((MyInterface)AopContext.currentProxy()).methodB();
    }
    
  • 我认为SpringAOP切入点需要在接口上声明,而不是在具体的类上声明,因为它们是基于代理的。第二部分是正确的,问题的根源在这里,第一部分是错误的。带有
    的CBLIG没有注册切入点。我认为Spring AOP切入点需要在接口上声明,而不是在具体的类上声明,因为它们是基于代理的。第二部分是正确的,问题的根源在这里,第一部分是错误的。带有
    的CBLIG没有得到要注册的切点。