在Guice应用程序中使用为Spring应用程序编写的切面。

huangapple go评论98阅读模式
英文:

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&lt;Object[]&gt; arguments, Supplier&lt;Object[]&gt; 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>



huangapple
  • 本文由 发表于 2020年8月21日 20:19:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/63522820.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定