如何通过长链方法调用共享内存?

时间:2017-10-31 13:59:25

标签: java oop design-patterns aop

我需要找出一种方法来有条理地保存和记录方法请求和响应,条件是顶级方法的延迟超过p50延迟。调用可视化为如下:

topLevel() -> method1() -> method2() -> ... -> makeRequest()

在makeRequest中,我需要记录对该请求的请求和响应。

但是我只知道在返回调用堆栈的过程中我是否需要实际记录那些 - 如果topLevel方法花费的时间太长。

所以对我而言,唯一的选择是在makeRequest中保存请求和响应,无论如何,并使topRevel方法可用。 topLevel方法将检查延迟是否高于p50并有条件地记录请求和响应。

这一切都导致了一个名义上的问题:如何通过长链方法调用共享内存?

我不希望通过多个方法调用传回对象,污染函数签名。

最好的模式是什么?也许使用本地缓存来保存请求和响应,然后在topLevel中检索它?是否有一种面向方面的方法来解决这个问题?

2 个答案:

答案 0 :(得分:1)

只要您控制了顶级代码并且通过method1method2,这真的不是那么难。

您只需要通过调用链传递请求,然后传回响应。

topLevel() -> method1(request) -> method2(request) -> ...
    -> makeRequest(request) { ... return response; }

要将此与实际代码示例相关联,您可以查看jersey框架的工作原理。

以下是注入请求并返回响应的方法示例。

@POST
@Consumes({MediaType.TEXT_XML})
@Produces({TEXT_XML_UTF_8})
public Response resource(@Context HttpServletRequest servletRequest) throws Exception {
    ExternalRequest req = makeRequest(servletRequest.getInputStream());
    ExternalResponse resp = externalGateway.doSomething(req);
    return Response.ok(wrapResponse(resp)).build();
}

虽然Jersey提供了一些花哨的注释(@Context等等),但这里没有任何明显的可区分设计模式 - 你只是传递请求对象并返回响应。

当然,您也可以维护缓存并将其传递给调用堆栈,或者实际上只是请求和响应的包装器对象,但它与简单地传递请求非常相似。

答案 1 :(得分:0)

此类功能最好使用ThreadLocals完成。您的makeRequest会将请求和响应对象添加到ThreadLocal中,然后topLevel将删除它们并在需要时记录它们。这是一个例子:

public class RequestResponseThreadLocal{

        public static ThreadLocal<Object[]> requestResponseThreadLocal = new ThreadLocal<>();
    }

    public class TopLevel{

        public void topLevel(){
            try{ 
                new Method1().method1();

                Object[] requestResponse = RequestResponseThreadLocal.requestResponseThreadLocal.get();

                System.out.println( requestResponse[0] + " : " + requestResponse[1] );
            }finally{
                //make sure to clean up stuff that was added to ThreadLocal otherwise you will end up with memory leak when using Thread pools
                RequestResponseThreadLocal.requestResponseThreadLocal.remove();
            }
        }
    }

    public class Method1{

        public void method1(){
            new Method2().method2();
        }
    }

    public class Method2{

        public void method2(){
            new MakeRequest().makeRequest();
        }
    }

    public class MakeRequest{

        public void makeRequest(){
            Object request = new Object();
            Object response = new Object();
            RequestResponseThreadLocal.requestResponseThreadLocal.set( new Object[]{request, response} );
        }
    }