英文:
Use an aspect written for spring application in guice application
问题
我曾经编写过一个使用Spring AOP/AspectJ注解的方面作为应用程序的一部分,类似于下面的方面:
@Aspect
@Component
public class LoggingAspect {
@Around("@annotation(loggable)")
public Object log(final ProceedingJoinPoint joinPoint, final Loggable loggable) throws Throwable {
//记录方法参数
try {
Object returnValue = joinPoint.proceed();
//记录返回值
return returnValue;
} catch (Exception ex) {
//将异常指标发布到其他系统
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 {
//调用已定义的log方法,但是该方法需要一个ProceedingJoinPoint作为输入参数,然而在这个方法中我得到的是MethodInvocation
}
//已定义的log方法
@Around("@annotation(loggable)")
public Object log(final ProceedingJoinPoint joinPoint, final Loggable loggable) throws Throwable {
...... //已有的代码
......
}
}
但由于这两个方法之间的不兼容类型,我无法继续进行。
有没有一种方法可以重用现有代码,而不是编写全新的具有重复代码的方面来支持Guice?
英文:
I had written an aspect as part of an application using Spring AOP/AspectJ annotations similar to below aspect:
@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;
}
}
}
Now I want to use this same aspect in another project, but this project uses Guice instead of Spring.
I was reading about Guice AOP which requires aspect to implement the MethodInterceptor interface and thus I will need to implement the below method:
Object invoke(MethodInvocation methodInvocation) throws Throwable;
What I was thinking was to modify the already existent aspect to implement the MethodInterceptor and internally call the log method. Something like below:
@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 {
......
.....
}
But due to incompatible type between two methods, I am unable to proceed.
Is there a way I can reuse the existing code instead of writing a brand new aspect with duplicate code to support Guice?
答案1
得分: 0
如果我理解正确,您想要颠倒控制流程,这可以通过回调函数来实现。
```java
@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();
//记录方法参数
try {
Object returnValue = proceed.get();
//记录返回值
return returnValue;
} catch (Exception ex) {
//将异常指标发布到其他系统
throw ex;
}
}
}
顺便问一下,您有意只捕获Exception
而不是Throwable
吗?Error
不会被记录。
<details>
<summary>英文:</summary>
If I understand correctly, you want to reverse the control flow, which can be done with callbacks.
@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;
}
}
}
---
BTW do you intentionally catch only `Exception` and not `Throwable`? `Error`s would not be logged.
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论