2012-01-14 71 views
0

問題描述:獨立編譯2個jar文件,而不必在classpath中包含對方;並在運行時將兩者都包含並在一個jar中調用main()以在stdout上打印字符串。輸出字符串的一部分必須來自第二個jar。帶Java註釋的「Hello World」

約束條件:該解決方案不能依賴於IDE或使用任何其他jar文件。

回答我到目前爲止所做的工作:我的解決方案如下所述。

問題的原因:我試圖弄清楚/如何使用註釋來解決這個問題(希望以更優雅的方式),但找不到任何合適的文檔或教程。我也很欣賞任何指針。

我的解決方案:一個批處理文件(在Unix上,請更改反斜槓斜槓,分號冒號和REM對#)如下:

rem Compile and package the testing class (Main) without any library 
javac -d target core\*.java 
cd target 
jar cvf ..\main.jar .\core 
cd .. 

rem Compile and package the Greeting and Greeted classes as a library 
javac -d lib impl\*.java 
cd lib 
jar cvf ..\mylib.jar .\impl 
cd .. 

rem Use the two parts above at runtime and execute main() in Main class 
java -cp main.jar;mylib.jar core.Main 

有2個文件中IMPL目錄2在覈心,如下所示:

/*文件:IMPL/Greeting.java */

package impl; 

public class Greeting { 
    public String getGreeting() { 
     return "Hello"; 
}} 

/*文件:IMPL/Greeted.java */

package impl; 

public class Greeted { 
    public String getGreeted() { 
     return "world"; 
} 

/*文件:核心/ Main.java */

package core; 

public class Main { 

    private String greeting = "Learn annotations",  greeted = "keep using Java", 

      // Can read the following 4 values from a configuration file, too 
      // Trying to see if we can get these using Java annotations 

      greetingClassName = "impl.Greeting", greetingMethod = "getGreeting", 
      greetedClassName = "impl.Greeted", greetedMethod = "getGreeted"; 

    public Main() { 
     try { 
      MyRunTime runTime = new MyRunTime(); 

      Object gting = runTime.getInstance(greetingClassName), 
       gted = runTime.getInstance(greetedClassName), 

       g1Str = runTime.getResponseNoArg (gting, greetingMethod), 
       g2Str = runTime.getResponseNoArg (gted, greetedMethod); 

      if (g1Str instanceof String) greeting = (String) g1Str; 
      if (g2Str instanceof String) greeted = (String) g2Str; 
     } catch (Exception ex) { 
      System.err.println ("Error in Library loading: " + ex.getMessage()); 
    }} 

    public void greet() { 
     System.out.println (greeting + ", " + greeted + "!"); 
    } 

    public static void main (String[] args) { 
     new Main().greet(); 
}} 

/*文件:核心/ MyRunTime.java */

package core; 

import java.lang.reflect.*; 

public class MyRunTime { 

    public Object getResponseNoArg (Object anInstance, String methodName) throws 
        NoSuchMethodException, 
         IllegalAccessException, 
         InvocationTargetException { 
     Method method = anInstance.getClass().getMethod (methodName); 
     return method.invoke (anInstance); 
    } 

    public Object getInstance (String className) throws 
        ClassNotFoundException, 
        InstantiationException, 
        IllegalAccessException { 
      Class c = Class.forName (className); 
      return c.newInstance(); 
    } 
} 

就是這樣。除非絕對必要,否則我也不想弄亂ClassLoader。一旦我掌握瞭如何使用註釋執行此操作,我可以查看傳遞的參數並繼續前進。感謝您的幫助。

+4

你說,「我試圖找出是否/如何使用註釋來解決這個問題。」爲什麼?關於註釋的含義是什麼使得您想要將它們用於描述的問題?這是功課嗎?有沒有*額外的*方向,你沒有給我們? – rfeak 2012-01-14 22:14:06

+0

爲什麼?詢問頭腦想知道。還有什麼...?不知何故,我所使用的大多數框架都使用註釋來進行依賴注入/ IoC /無論你怎麼稱呼它。這些框架的創造者無疑是聰明的人,我試圖理解他們的邏輯。不,這不是任何作業。其他指示:我不確定你的意思,但我所描述的幾乎是一個完整的描述。從你的評論中,我應該假設答案是「註釋與描述的問題無關」? – 2012-01-14 22:52:09

+0

是的,那將是我的意見。我不認爲註釋會增加很多解決問題描述的方式。我見過的大多數Annotation用法都涉及到爲類定義額外的*行爲,而不是如何定位它。 – rfeak 2012-01-15 09:10:29

回答

0

我不會爲此使用註釋 - 它可能值得介紹註釋是什麼以及它們的最佳使用位置。

相反,我會做這樣的事情:

  • 將不同文件中的每個罐子
  • 主類,以每個jar文件,它做同樣的事情:名單上的類路徑中的文件

我認爲這將符合項目要求。

要列出類路徑的文件,你可以這樣類似:

public class Main { 
    public static void main(final String[] args) throws java.lang.Throwable { 
    final String list = System.getProperty("java.class.path"); 
    for (String path : list.split(";")) { 
     java.io.File object = new java.io.File(path); 
     if (object.isDirectory()) 
     for (String entry : object.list()) { 
      java.io.File thing = new java.io.File(entry); 
      if (thing.isFile()) 
      System.out.println(thing); 
      else if(object.isFile()) 
      System.out.println(object); 
     } 
    } 
    } 
} 
+0

讓我重新解釋這個問題。在編譯包含Main.main(String [])方法的「a.jar」時,我們不知道「b.jar」是否存在,甚至不知道它包含的類。 Main類不知道它需要的對象或要調用的方法(在我的例子中,變量xxClassName和xxMethod要在運行時從配置文件讀入)。你所建議的是掃描classpath上的每個jar文件,並檢查命名對象(class)是否存在於其中的一個。我已經可以使用Class.forName()來做到這一點,並使用反射來檢查方法。這就是我現在正在做的。 – 2012-01-14 23:47:52

+0

我在找的是我如何讀取帶有值(例如Greeting)的註解(例如greetingClassName),然後在運行時查找註釋爲「@Greeting」的類。這樣,我可以有幾個Greeting類的實現(在不同的jar文件甚至包中),然後用正確的註解選擇一個。這是使用註釋的好方法,還是我完全不符合標準? – 2012-01-14 23:54:35

+0

如果你在jar A中定義了一個註釋,你將在你使用的所有jar中創建一個編譯和運行時依賴 - 這違反了規範。 – 2012-01-15 00:04:46