Java 合并Guice和AOP

Java 合并Guice和AOP,java,aop,guice,Java,Aop,Guice,我正在构建一个包,该包试图根据标志截取函数的返回值。我的设计涉及一些AOP。其思想是类FirstIntercept拦截调用firstCall,并将参数存储在parameters对象中。然后,第二个类SecondIntercept截取另一个调用secondCall,并根据参数中填充的内容执行一些逻辑: // pseudoish code public class FirstIntercept { private Parameters param; @AfterReturning(p

我正在构建一个包,该包试图根据标志截取函数的返回值。我的设计涉及一些AOP。其思想是类
FirstIntercept
拦截调用
firstCall
,并将参数存储在
parameters
对象中。然后,第二个类
SecondIntercept
截取另一个调用
secondCall
,并根据
参数中填充的内容执行一些逻辑:

// pseudoish code 
public class FirstIntercept {
   private Parameters param;

   @AfterReturning(pointcut = "execution(* ...firstCall(..))", returning = "payload")
   public void loadParam(Joinpoint joinPoint, Object payload) {
      // logic handling payload returned from firstCall()
      // logic provides a Boolean flag
      this.param = new Parameters(flag);
   }
}



public class Parameters {
   @Getter
   private Boolean flag;

   public Parameters(Boolean flag) {
      this.flag = flag;
   }
}



public class SecondIntercept {
   private static Parameters params;
   
   @Around("execution(* ...secondCall(..))")
   public void handleSecondCallIntercept(ProceedingJoinPoint joinPoint) {
      // want to do logic here based on what params contains
   }
}
我想要实现的是,当通过AOP调用
FirstIntercept.loadParam
时,将一次性加载
参数
对象。我不太确定我怎样才能坚持下去。我在网上看了看,谷歌guice似乎很有前途。我相信第一步是在
参数上使用依赖注入,但我真的不确定。有人能帮我指出正确的方向吗


编辑:

所以我尝试了这个设置:

public class FirstIntercept implements MethodInterceptor {
   public Object invoke(MethodInvocation invocation) throws Throwable {
      System.out.println("invoked!");
      return invocation.proceed();
   }

   @AfterReturning(pointcut = "execution(* ...firstCall(..))", returning = "payload")
   public void loadParam(Joinpoint joinPoint, Object payload) {
      // do stuff
   }

   public String firstCall() {
      return "hello";
   }
}

public class InterceptionModule extends AbstractModule {
   protected void configure() {
      FirstIntercept first = new FirstIntercept();
      bindInterceptor(Matchers.any(), Matchers.annotatedWith(AfterReturning.class), first);
   }
}

public class FirstIterceptTest {
   @Test
   public void dummy() {
      Injector injector = Guice.createInjector(new InterceptionModule());
      FirstIntercept intercept = injector.getInstance(FirstIntercept.class);

      intercept.firstCall();
   }
}

当我执行
.firstCall()
时,我可以看到
@在返回后运行
,但调用没有被调用。

如果您扩展AOP的文档,您应该会得到一些接近:

公共类FirstInterceptor实现MethodInterceptor{
@注入参数参数;//注入单例参数
公共对象调用(MethodInvocation调用)抛出可丢弃的{
对象结果=调用。继续();
//基于结果设置参数的逻辑。setFlag()
返回结果;
}
}
然后第二个:

公共类SecondInterceptor实现MethodInterceptor{
@注入参数参数;//注入单例参数
公共对象调用(MethodInvocation调用)抛出可丢弃的{
布尔标志=参数。getFlag();
//你的逻辑在这里
返回调用。继续();//可能不是?
}
}
您的参数是关键,您需要确保它是线程安全的,这是另一个主题。但要注入这些,您需要:

公共类拦截模块扩展了AbstractModule{
受保护的void configure(){
//确保只注入一个参数
bind(Parameter.class).in(Scopes.SINGLETON);
//现在注入并绑定第一个拦截器
FirstInterceptor FirstInterceptor=新的FirstInterceptor();
请求注入(第一拦截器);
bindInterceptor(Matchers.any()、Matchers.annotatedWith(AfterReturning.class)),
第一拦截器);
//现在注入并绑定第二个拦截器
SecondInterceptor SecondInterceptor=新的SecondInterceptor();
请求注入(第一拦截器);
bindInterceptor(Matchers.any()、Matchers.annotatedWith(AfterReturning.class)),
第二拦截器);
}
}
编辑 看看你在做什么

  • 您告诉Guice用@AfterReturn和FirstInterceptor包装一个方法
  • 然后调用拦截器。firstCall()
  • 第一个调用没有@AfterReturn注释,那么为什么它会与该配置匹配呢

    我猜如果你打电话:

    intercept.loadParam();
    
    您将看到invoke方法。此外,这对于测试来说非常好,但在现实生活中,您希望服务级别类具有@AfterReturn,然后将其注入另一个调用LoadParam的Api/Job/Etc

    编辑 哦,不,看看这条线

    bindInterceptor(Matchers.any(),//具有此matcher的类
    Matchers.annotatedWith(AfterReturning.class),//具有以下内容的方法
    第一拦截器);
    

    这意味着喷油器仅在loadParams上点火。您需要用@AfterReturning注释您所属类的方法,以导致拦截。您希望loadParams成为invoke方法。

    我将
    invoke
    方法添加到
    FirstInterceptor
    ,但即使在返回
    @注释的方法后
    @未被调用,它也不会被调用。我确保实例化
    Guice.createInjector(new InterceptionModule())
    并使用
    injector.getInstance(FirstInterceptor.class)
    阅读AOP上的规则,不能是私有的、最终的等。另外,我不知道您在哪里使用injector.getInstance()。为了提供更好的详细信息,我需要查看更多/所有代码。您正在调用一个返回后未使用
    @注释的方法。如果希望拦截器拦截所有类方法,只需切换matcher并将注释放在类上。但是要确保添加了服务类,千万不要用相同的拦截器包装拦截器类。哦,我想任何时候,在返回
    后用
    @注释的方法,都会调用
    调用
    。我很困惑:我永远不会直接调用
    intercept.loadParam()
    ,因为
    loadParam()
    只有在调用
    firstCall()
    时才会被触发。你是对的。任何带有@afterretuening注释的方法都将调用。但是你没有打电话给loadParam。你打了第一个电话。FirstCall没有注释。LoadParam是。那么为什么firstParam会触发它呢?您需要将注释移动到firstcall方法。