繁体   English   中英

扩展抽象控制器的控制器中方法的自定义注释

[英]Custom annotation for method in controller that extends an abstract controller

我要做的是使用拦截器非常简单,但是我确实希望基于注释的一种更优雅的解决方案。 问题是我的“解决方案”并没有真正起作用,我也不知道为什么。 也许这甚至是不可能的。

我的基本堆栈是:spring boot 1.4.1:

  • 弹簧引导启动的Web
  • 弹簧引导启动的AOP
  • 弹簧引导启动-JDBC
  • 弹簧引导启动缓存

spring-beans 4.3.4以及其他各种实用程序和测试罐。

我有几个扩展抽象控制器的控制器。 这个抽象控制器必须准备一个连接,然后每个控制器都使用放置在acquire()方法中的自己的特定实现。 有时,一些cron作业正在达到这个目标。 我们想对某些控制器/作业进行审核,但不一定要对所有控制器/作业进行审核。 因此,我正在考虑在审核位置添加自定义注释。

public abstract class ImportController { 
    @RequestMapping(value = "/checkout", method = RequestMethod.GET, produces = "application/json")
    public String importEntities() {
         //some code here ....
         MyResult result = acquire(param);
         //some code again ....
    }

     public abstract MyResult acquire(MyParam param)
}

需要审核的实施:

@RestController
@RequestMapping(value = "/cars")
public class CarsImportController extends ImportController {

     @Override
     @MyJobAudit // <--- this should add a pointcut used for Audit logging
     public MyResult acquire(MyParam param) {
          //cars specific code
     }
}

无需审核的实施

@RestController
@RequestMapping(value = "/tomatoes")
public class TomatoesImportController extends ImportController {

     @Override
     //no audit annotation
     public MyResult acquire(MyParam param) {
           //tomatoes specific code
     }
}

我的JobAudit批注:

@Retention(RetentionPolicy.RUNTIME)
    public @interface MyJobAudit {
}

和方面类:

@Aspect
@Component
public class SystemAspectArchitecture {
    @Pointcut("@annotation(MyJobAudit)")
    public void auditableJob() {
    }
}

我试图将注释放在各种服务类上,并且可以正常工作。 但不是在acquire()方法上。 这里肯定有问题。 我不知道是什么...

问题出在建议代码的调用上。 您会看到,您定义了以下代码:

@GetMappein(value = "/checkout")
public String getCheckout() {
   //some code here ....
   MyResult result = acquire(param); //Uh oh!!!
   //some code again ....
}

但是问题是建议的代码是在Spring为您创建的代理中定义的(对于控制器您从未看到过),但是您对上面的acquire(param)方法的调用没有在Spring代理中完成,但是直接在您的具体类上,换句话说,等效于说this.acquire(param) ,但是代码在this的代理中建议使用,而不仅仅是在this (您的具体对象)上使用。

解决问题的方法是访问您当前的代理。 我如下解决。

首先,在您的应用程序中启用expose-proxy

@SpringBootApplication
@EnableAspectJAutoProxy(exposeProxy = true)
public class MyApplication {

    public static void main(String[] args) {
        SpringApplication.run(MyApplication, args);
    }
}

然后,在具体的类中,您打算调用应该建议使用的方法,请执行以下操作:

@RestController
public class ConcreteController {

    @GetMapping("/checkout")
    public String getSomething() {
        Object proxy = AopContext.currentProxy();
        return ((ConcreteController) proxy).acquire("Luke Skywalker");
    }

    @Auditable
    public String acquire(Object param) {
        return "Hello World, " + param;
    }

}

AopContext.currentProxy()将允许您访问this控制器的代理,在该代理中实际定义了acquire(params)的建议。 它将按预期工作。

我知道唯一的解决方法是使用真正的AOP,而不仅仅是Spring代理。 而且,如果使用真正的AOP,则必须进行某种形式的代码编织,以在编译或加载期间为代码提供建议。 这样,将直接在具体的类上建议代码,而不仅仅是在愚蠢的Spring代理上建议代码。 使用真正的AOP时,将在编译时或加载时通过检测来建议this.acquire() 但是,如果仅使用Spring代理,则无法直接在建议的类中执行诸如直接方法调用之类的操作,因此您需要确保每次执行代理操作时都要经过代理。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM