我有一个Java实用程序包,可以由多个服务(用Java编写)用于执行某些实用程序任务。
假设Java实用程序包名称为U,其中一个Service为S. Now.S调用U的函数F.
我的问题是,是否有一种方法,包U的功能F能够确定哪个服务S调用了它? 可以有多个服务S1,S2,...,Sn呼叫F.我需要知道一个呼叫,哪个服务Sx正在呼叫该特定的F.
答案 0 :(得分:4)
您可以使用类似下面的内容,只需要创建函数findServiceContainingClass
将类名映射到服务(或null):
void callee() {
StackTraceElement[] st = new RuntimeException().getStackTrace();
for (int i = 1; i < st.length; i++) {
Service service = findServiceContainingClass(st[i].getClassName());
if (service != null) break;
}
// ... use service
}
然而,根据调用者的不同,使代码行为不同被认为是不好的做法。我会将此类代码仅作为最后的手段。 (在调试期间可以在断点条件下使用它。也许这就是你想要的。)
答案 1 :(得分:2)
Java中的面向对象编程声明您的服务是调用的范围,没有别的(忘记static
)。因此除了将S
实例作为参数传递之外,没有正常的方法可以找到调用实例方法的人。
但这并不意味着它是不可能的。
如果您只需要知道来电者的类型,可以使用Thread.currentThread().getStackTrace()
:
StackTraceElement[] elements = Thread.currentThread().getStackTrace()
StackTraceElement caller = elements[elements.length - 2];
printLn(caller.getClassName());
正如我在开头所说,它完全是反客观的Java代码。
如果您需要引用确切的实例,您可能应该将调用者添加为调用参数。我假设如果你想引用调用者,callee的代码是由你编写的,所以你可以这样做。 至于我这是最好的选择,因为如果你需要在被调用者范围内调用者,你应该直接传递它。 其他选项是在{{{{em>上设置调用者1}},但你不相信开发人员每次都会这样做。
如果无法更改界面,并且U是界面,则可以创建U
构建器对象:
U
之后,您有另外的调用上下文(public class UBuilder {
public U getS(final S caller) {
Proxy.newProxyInstance(getClass().getClassLoader(), U.class,
new InvocationHandler() {
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
// store caller value on some ThreadLocal variable
try {
method.invoke(proxy, args);
} finally {
// remove caller from ThreadLocal variable
}
}
}
}
}
)引用ThreadLocal
实例。
如果S
不是界面,U
,Javassist
或类似内容会有所帮助,但前提是调用的方法不是静态的或最终的。
如果CgLib
是静态的或最终的,我只会看到极其苛刻的答案。也许创建自己的模仿F
的界面,U
中的转发方法调用可能是某种方式。当然S应该引用这个接口,而不是直接InvocationHandler
。
希望它有所帮助。
答案 2 :(得分:0)
如果需要一些由该实用程序方法执行的特定于服务的代码,我将在实用程序类中声明一个接口,并让服务将其实例传递给该方法。
这是一个人为的例子:
public class Utility {
public interface UtilityInterface {
public void specificBehavior( Object arg );
}
public void utilityMethodF( UtilityInterface utilityInterface, Object... args ) {
// perform work with args or whatever
utilityInterface.specificBehavior( null );
// perform work with args or whatever
}
}