2016-06-28 26 views
2

我想编写一个实用程序,它可以为请求和响应进行(相对)非侵入式的日志记录,并且希望能够使用java-8 lambda/functional接口来完成它。通过函数/供应商访问lambda参数

比方说,在样本客户端调用代码:

SomeReturn retVal = someObject.doSomething(arg1, arg2); 

我希望写一个记录工具,可以被调用为:

SomeReturn retVal = Recorder.withRecording(() -> someObject.doSomething(arg1, arg2)) 

记录器看起来像:

public static <R> R withRecording(Supplier<R> call) { 
    R response = call.get(); 
    // Record the response 
    return response; 
} 

但是,我无法确定一种方法来捕获请求参数(和reque st对象)从Supplier(和正确的 - Supplier不关心它)。我认为即使java.util.function.Function也不会帮助我们,因为它们不涉及国家本身。

没有求助于之类的东西

Object withRecording(Object target, Method method, Object[] arguments) 

我们有什么其他选择?我知道我们可以使用AOP作为解决方案,但希望看看我们能否在没有它的情况下做到。

在此先感谢!

+2

即使有可能(并且我不认为它是简单的),您会使用千Recorder.withRecording'。当你想要禁用/删除该录音的那一天,你会吃你的帽子。正如你所说,这听起来像是AOP的完美场景。 – Tunaki

回答

4

这只适用于使用已知的有限功能签名集合进行操作的情况,例如,

public static <T,U,R> R withRecording(BiFunction<T,U,R> func, T arg1, U arg2) { 
    R response = func.apply(arg1, arg2); 
    // Record arg1, arg2 and the response 
    return response; 
} 

可用作

SomeReturn retVal = withRecording(someObject::doSomething, arg1, arg2); 

这不仅意味着你必须创建为每个支持的签名一个过载,即不同数量的参数,你还必须为每一个功能的适当接口有两个以上的参数,因为这些情况下没有预定义的接口。

而且,请注意函数对象本身不会透露实际的功能什么,所以你要录制的是一些功能已经调用与特定参数和结果,而不是其功能...


一个更好的解决办法是声明为一个接口方法doSomething,允许与参照另一种实现方式,委托给someObject并记录所有调用替换someObject。这个功能可以通过使用代理的一般方式来实现,但是,与AOP解决方案重叠...

+0

接受它作为对代理的引用和与AOP重叠的答案。 – Kilokahn