Java 带注释的Spring AOP方面不适用于基类

Java 带注释的Spring AOP方面不适用于基类,java,spring,inheritance,annotations,aop,Java,Spring,Inheritance,Annotations,Aop,我的注释定义如下 @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface OTPFlow { } public abstract class A { @OTPFlow public ModelAndView doSomething() { //do something and return ModelAndVi

我的注释定义如下

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface OTPFlow {
}
public abstract class A {
  @OTPFlow
  public ModelAndView doSomething() {
    //do something and return ModelAndView
  }
}
@Controller
@RequestMapping(value = {"/someurl"})
public class B extends A {
  @RequestMapping(value = {"/get"}, method = {RequestMethod.POST, RequestMethod.GET})
  public ModelAndView get(HttpServletRequest request, HttpServletResponse response) {
    return doSomething();
  }
}
A类的定义如下

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface OTPFlow {
}
public abstract class A {
  @OTPFlow
  public ModelAndView doSomething() {
    //do something and return ModelAndView
  }
}
@Controller
@RequestMapping(value = {"/someurl"})
public class B extends A {
  @RequestMapping(value = {"/get"}, method = {RequestMethod.POST, RequestMethod.GET})
  public ModelAndView get(HttpServletRequest request, HttpServletResponse response) {
    return doSomething();
  }
}
B类是定义如下的控制器

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface OTPFlow {
}
public abstract class A {
  @OTPFlow
  public ModelAndView doSomething() {
    //do something and return ModelAndView
  }
}
@Controller
@RequestMapping(value = {"/someurl"})
public class B extends A {
  @RequestMapping(value = {"/get"}, method = {RequestMethod.POST, RequestMethod.GET})
  public ModelAndView get(HttpServletRequest request, HttpServletResponse response) {
    return doSomething();
  }
}
方面定义为

@Component
@Aspect
public class OTPAspect {
private static final Logger logger = LoggerFactory.getLogger(OTPAspect.class);

@Pointcut("@annotation(OTPFlow)")
public void OTPFlow() {}

@Around("OTPFlow()")
public Object checkOTP(ProceedingJoinPoint joinPoint) {
    try {
        logger.info("Inside Aspect");
        return joinPoint.proceed();
    } catch (Throwable e) {
        throw new RuntimeException(e);
    }
}
}
问题是,当我访问“/someurl/get”url时,该方面不会执行。但当我注释类B的“get”方法时,就会执行方面

所以基本上,超类的带注释的方法不会调用方面


问题是什么?有没有其他方法可以做到这一点?任何帮助都将不胜感激。感谢

当spring应用方面时,会发生什么事情呢?spring创建代理来包装您的控制器实例以拦截调用,并在调用实例方法之前添加方面行为。这样做的效果是,从控制器实例中对“This”的任何调用都将直接在该实例上调用,而不会被包装代理截获。因此,在代理类上调用“get”方法,代理类将调用控制器实例的“get”方法,当后者尝试调用“doSomething”方法时,它将不会通过代理的“doSomething”,而是通过内部方法


处理这种情况的方法是将方面直接应用于类中将被外部调用的方法,在您的情况下,直接应用于“get”方法,而不是“doSomething”

当spring应用方面时会发生什么,是因为spring创建了代理来包装控制器实例以拦截调用,并在调用实例方法之前添加方面行为。这样做的效果是,从控制器实例中对“This”的任何调用都将直接在该实例上调用,而不会被包装代理截获。因此,在代理类上调用“get”方法,代理类将调用控制器实例的“get”方法,当后者尝试调用“doSomething”方法时,它将不会通过代理的“doSomething”,而是通过内部方法


处理这种情况的方法是将方面直接应用于类中将被外部调用的方法,在您的情况下,直接应用于“get”方法,而不是“doSomething”

当spring应用方面时会发生什么,是因为spring创建了代理来包装控制器实例以拦截调用,并在调用实例方法之前添加方面行为。这样做的效果是,从控制器实例中对“This”的任何调用都将直接在该实例上调用,而不会被包装代理截获。因此,在代理类上调用“get”方法,代理类将调用控制器实例的“get”方法,当后者尝试调用“doSomething”方法时,它将不会通过代理的“doSomething”,而是通过内部方法


处理这种情况的方法是将方面直接应用于类中将被外部调用的方法,在您的情况下,直接应用于“get”方法,而不是“doSomething”

当spring应用方面时会发生什么,是因为spring创建了代理来包装控制器实例以拦截调用,并在调用实例方法之前添加方面行为。这样做的效果是,从控制器实例中对“This”的任何调用都将直接在该实例上调用,而不会被包装代理截获。因此,在代理类上调用“get”方法,代理类将调用控制器实例的“get”方法,当后者尝试调用“doSomething”方法时,它将不会通过代理的“doSomething”,而是通过内部方法


处理这种情况的方法是将方面直接应用于将被外部调用的类的方法,在您的例子中,直接应用于“get”方法而不是“doSomething”

我想提供一种替代M.Deinum和Marios正确说过的方法:使用AspectJ而不是Spring AOP。AspectJ不依赖于代理,速度更快、功能更强大,并且与Spring手册中描述的Spring很好地集成。有了AspectJ,你想做的事情是现成的。

我想提供一个替代M.Deinum和Marios所说的正确的选择:使用AspectJ而不是Spring AOP。AspectJ不依赖于代理,速度更快、功能更强大,并且与Spring手册中描述的Spring很好地集成。有了AspectJ,你想做的事情是现成的。

我想提供一个替代M.Deinum和Marios所说的正确的选择:使用AspectJ而不是Spring AOP。AspectJ不依赖于代理,速度更快、功能更强大,并且与Spring手册中描述的Spring很好地集成。有了AspectJ,你想做的事情是现成的。

我想提供一个替代M.Deinum和Marios所说的正确的选择:使用AspectJ而不是Spring AOP。AspectJ不依赖于代理,速度更快、功能更强大,并且与Spring手册中描述的Spring很好地集成。使用AspectJ,您想做的事情是现成的。

Spring使用代理,只截获对对象的方法调用,您是在内部调用一个方法。这里有一种“变通”方法可以完成,而不必求助于完整的AspectJ。只需创建一个“原型范围”的bean,它为您提供了一种创建临时代理的方法(通过实例化bean的实例),然后如果您将这个bean上的方法作为切入点的目标,那么实例化的bean将是它自己的代理,因此AOP将被正确调用。显然,您只会在有限的情况下使用它,而不会将其作为体系结构的核心部分,但是在您需要Spring AOP无法提供的东西的情况下,这种“原型”技巧可以发挥作用。Spring使用代理,只截获对对象的方法调用,您在内部调用方法。有一种“变通方法”这是可以做到的,