【问题标题】:Use an aspect written for spring application in guice application在 guice 应用程序中使用为 spring 应用程序编写的方面
【发布时间】:2020-08-22 20:31:58
【问题描述】:

我使用类似于以下方面的 Spring AOP/AspectJ 注释编写了一个方面作为应用程序的一部分:

@Aspect
@Component
public class LoggingAspect {
    @Around("@annotation(loggable)")
    public Object log(final ProceedingJoinPoint joinPoint, final Loggable loggable) throws Throwable {
        //log method arguments
        try {
            Object returnValue = joinPoint.proceed();
            // log return value
            return returnValue;
        } catch (Exception ex) {
            // publish exception metrics to some other system
            throw ex;
        }
    }
}

现在我想在另一个项目中使用同样的方面,但是这个项目使用 Guice 而不是 Spring。

我正在阅读Guice AOP,它需要方面来实现 MethodInterceptor 接口,因此我需要实现以下方法:

Object invoke(MethodInvocation methodInvocation) throws Throwable;

我的想法是修改已经存在的方面以实现 MethodInterceptor 并在内部调用 log 方法。如下所示:

@Aspect
@Component
public class LoggingAspect implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        // call already defined log method, but that method expects a ProceedingJoinPoint, however
        // I get MethodInvocation as input parameter in this method
    }

// already defined log method
@Around("@annotation(loggable)")
    public Object log(final ProceedingJoinPoint joinPoint, final Loggable loggable) throws Throwable {
......
.....
}

但是由于两种方法之间的类型不兼容,我无法继续。

有没有一种方法可以重用现有代码,而不是使用重复代码编写全新的方面来支持 Guice?

【问题讨论】:

    标签: java spring aop guice aspectj


    【解决方案1】:

    如果我理解正确,你想反转控制流,这可以通过回调来完成。

    @Aspect
    @Component
    class LoggingAspect implements MethodInterceptor {
        @Around("@annotation(loggable)")
        public Object log(final ProceedingJoinPoint joinPoint, final Loggable loggable) throws Throwable {
            return log(joinPoint::getArgs, () -> joinPoint.proceed(joinPoint.getArgs()));
        }
        
        @Override
        public Object invoke(MethodInvocation methodInvocation) throws Throwable {
            return log(methodInvocation::getArguments, methodInvocation::proceed);
        }
    
        public Object log(Supplier<Object[]> arguments, Supplier<Object[]> proceed) {
            Object[] args = arguments.get();
            //log method arguments
            try {
                Object returnValue = proceed.get();
                // log return value
                return returnValue;
            } catch (Exception ex) {
                // publish exception metrics to some other system
                throw ex;
            }
        }
    
    }
    

    顺便说一句,您是否故意只捕获 Exception 而不是 ThrowableErrors 不会被记录。

    【讨论】:

    • 谢谢老鹰,你的建议奏效了。关于仅捕获 Exception 而不是 Throwable,我不知道它们之间的差异。将评估我是否需要捕获 Throwable。
    猜你喜欢
    • 1970-01-01
    • 2020-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多