确保一种方法';s调用堆栈在Java中始终包含另一个方法
我在Java项目中使用的一个公共实用程序中有一个设计问题,我想确保特定方法a的所有调用者都被另一个方法B包装起来。正如我今天所写的代码的一般形式是:确保一种方法';s调用堆栈在Java中始终包含另一个方法,java,static-analysis,call-hierarchy,Java,Static Analysis,Call Hierarchy,我在Java项目中使用的一个公共实用程序中有一个设计问题,我想确保特定方法a的所有调用者都被另一个方法B包装起来。正如我今天所写的代码的一般形式是: x.B(new Runnable() { y.A(); }); B正在执行的runnable可以有任意代码,并且可能多次调用A,因此我无法通过将对A的调用直接添加到B中来摆脱代码中的runnable。此外,A是第三方代码,因此我们无法修改它。runnable可能会再次调用B,并对A进行另一个嵌套调用,但今天这种情况从未发生过,所以我现在可
x.B(new Runnable() {
y.A();
});
B正在执行的runnable可以有任意代码,并且可能多次调用A,因此我无法通过将对A的调用直接添加到B中来摆脱代码中的runnable。此外,A是第三方代码,因此我们无法修改它。runnable可能会再次调用B,并对A进行另一个嵌套调用,但今天这种情况从未发生过,所以我现在可以忽略这种情况
我看到一些选择:
A()抛出BlahException
,并使其成为该异常的唯一捕获者。这很难看,因为没有任何应该真正抛出的异常,但这很好,因为编译器将为我确保调用层次结构A
的每次调用,检查stacktrace中的方法B
。如果它不在那里,您可以抛出异常来阻止执行A
,或者将错误写入日志,或者执行任何您喜欢的操作。大概是这样的:
@Aspect
public class CheckInsideMethodBAspect {
@Around("execution(* com.example.AClass.A(..))")
public void checkNestedMethod(ProceedingJoinPoint joinPoint) {
// checking for method B in the call stack
boolean isInsideB = false;
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
for (StackTraceElement element: stackTraceElements) {
if (element.getClassName().equals("ClassB") && element.getMethodName().equals("B")) {
isInsideB = true;
break;
}
}
// if not inside B, throwing exception
if (!isInsideB) {
throw new NotInsideBException();
}
// if inside B, then proceeding with method A execution
joinPoint.proceed();
}
}
这在很大程度上是一种反模式。方法
A
不应该关心是谁调用它。为什么您认为需要这样做?您是否尝试使用代理模式?@KevinKrumwiede-可能A
不知道其调用方,项目希望所有对A
的调用都被包装。@gerty3000-其他选项:1)记录需求并执行代码审查,以及2)面向方面的编程。前者重量轻,但不能保证。后者似乎相当重。@KevinKrumwiede:同意;这是为了解决第三方代码中的一个bug(具体地说,是从本机代码回调到Java的JNA),该bug最终导致本机堆耗尽,我们的包装器将防止这种情况。如果抽象没有泄漏,我们就不在乎是谁在调用它。无论调用堆栈中方法B
的要求背后的原因是什么,也就是说,无论方法B
做了什么,这都是非常重要的,都可以通过这种方法直接实现,将B
排除在外。