2013-11-24 83 views
1

我有一個Java實用程序包,可以由多個服務(用Java編寫)用於執行一些實用程序任務。被叫方是否知道來電者?

比方說在Java應用程序包的名稱是U和服務的一個是S.現在全叫U的函數F

我的問題是,是否有一種方法,其中封裝的函數F U是能夠確定S所稱的服務? 可以有多個服務S1,S2,...,Sn調用F.我需要知道一個調用,哪個Service Sx正在調用那個特定的F.

+0

沒有什麼好的方法。這聽起來像你應該將具體信息傳遞給'F'關於誰叫它。 –

+0

爲什麼實用程序類需要知道哪個客戶端類正在調用它?實用程序類將如何改變其行爲以適應不同的客戶端類型? – Bobulous

+0

看看您是否可以使用F的任何方法參數並對其進行處理。請在服務中調用方法的任何方法參數(如果可能)中設置服務名稱或代碼值。 – Nishant

回答

4

您可以使用類似下面的內容,只需要然而,它被認爲是不好的做法,使代碼的行爲不同,這取決於主叫

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 
} 

:創建一個函數映射findServiceContainingClass類名服務(或空)。我只會將這些代碼作爲最後的手段。 (可以在調試過程中在斷點狀態下使用它,也許這就是你想要的)

0

如果需要一些由該實用程序方法執行的服務特定的代碼,我會聲明一個接口在實用程序類中,並將這些服務的實例傳遞給該方法。

這是一個人爲的例子:在Java中

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 
    } 

} 
2

面向對象的編程指出您的服務範圍進行調用,沒有別的(忘了static)。因此,除了傳遞S實例作爲參數之外,沒有正常的方法可以找到誰在調用實例的方法。

但這並不意味着它是不可能的。

如果你只需要知道什麼是來電者的類型,你可以使用Thread.currentThread().getStackTrace()

StackTraceElement[] elements = Thread.currentThread().getStackTrace() 
StackTraceElement caller = elements[elements.length - 2]; 
printLn(caller.getClassName()); 

正如我在開始的時候是完全反客觀Java代碼表示。

如果您需要參考確切實例,您可能應該添加調用者作爲調用參數。我假設,如果你想引用調用者,被調用者的代碼是由你寫的,所以你能夠做到。 至於我這將是最好的選擇,因爲如果你需要調用者在被調用者的範圍內,你應該直接傳遞它。其他選項是在0123B的ThreadLocal上設置調用者,但是您沒有信心開發人員每次都會這樣做。

如果接口不能改變,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 
     } 
     } 
    } 
    } 
} 

之後,你有提到S例如額外的調用上下文(ThreadLocal)。

如果U沒有接口JavassistCgLib或類似,將有助於東西,但是隻有當調用的方法是不是靜態或決賽。

如果F是靜態的或最終的我只看到極其駭人的答案。也許創建自己的界面模仿U,轉發方法調用InvocationHandler可能是某種方式。當然S應該直接指這個接口,而不是U

希望它有幫助。

相關問題