2012-01-14 127 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