最近项目中,遇到了一个问题,起因是这个样子的:
项目A,它是一个web项目(使用spring开发,tomcat下部署,提供jsp页面,供用户使用),会引入产品包,暂且用product.jar来代替产口包吧吧。web项目最后会打成war包来部署。
项目B,它呢,不需要页面,换言之,它也是web项目(使用spring开发,tomcat下部署),只是单纯的引入spring的定时任务来处理业务数据。说到底,它也是一个web项目,只不过不需要html,jsp这些东东,类似于windows里的服务吧,不需要有GUI窗口。它最终也是打成war包来发布。但是,和项目A的不同之处在于它需要把项目A,先打成JAR包,然后放在项目B中引用。这么想像或许可以更为直接:项目A中,定义了好多实体类,然后在项目B中引入项目A的JAR包,这么说理,便顺理成章了。
说到这里,介绍了两个项目之间的关系。那么,问题也就随之而来了:
产品包product.jar中,有个Order类,它继承了抽像类AbstractOrder类。如下所示:
public class Order extends AbstractOrder{
}
order里什么属性也没有,产品的设计思想是,每个项目都会有自己的业务,在这里写自己的代码(比如属性)。而AbstractOrder里,则是产品里的自己的代码。
我们在Order里添加自己的属性,然后发布项目A时,什么问题都没有。
现在发布项目B,先把项目A打成jar包,把项目B打成WAR包(WAR包里的LIB目录会含有项目A的JAR文件)。启动项目时却报错了,大致是找不到Order里的属性。。。
到目前为止,项目B里,存在了两个Order类,一个是产品包里的,一个是项目A打成的JAR包里的。两个Order,到底用的哪个呢,系统又是怎么控制的呢?所以引入话题:
同包同名的类,会先加载哪个呢???
同样的问题,我们在开发中经常会引入第三方的JAR,很有可能会出现同名字的类(这里是指同包,同类),那么VM是怎么样决定使用哪个的呢?
先在Eclpise中做个例子。
Order里的代码如下所示:
package org.test;
public class Order {
public void say() {
System.out.println("这是JAR文件里的");
}
}
package org.test;
public class TestMain {
public static void main(String[] args) {
Order order = new Order();
order.say();
}
}
运行TestMain,打印如下所示:
上面的输出再正常不过了。接下来,模拟下把这个项目打成JAR文件。然后下一步,再放到当前这个项目里进行引用。另外,改下代Order里的代码。
Order里现在的代码为
package org.test;
public class Order {
public void say() {
System.out.println("这是项目里的");
}
}
说下刚才的动作。Order里的代码(“这是JAR文件里的”)已经被打成JAR包(文件名为ac.jar)了,并且在项目中引用了。然后又把项目里的Order的代码,输出换成了"这是项目里的"。到目前为目,两个Order对象了吧(同包同类名),那么到底用哪个呢?再运行一下,看看什么结果
这是项目里的
结果显示,用的是项目里的。第一个问题:为什么是用的项目里的呢?第二个问题:能不能告诉eclpise用JAR文件里的呢?
先来回答第二个问题,是可以的。可以告诉eclipse用JAR里的。具体做法如下
如题所示,只要让ac.jar,处理列表中的第一条即可。选中ac.jar,点击右侧的top即可。然后再运行一下,就会发现用的是JAR文件里的了。
再来回答第一个问题:为什么会这样呢?
长话短说,这个类加载器用关。即classloader。
再抛出一个问题,这是在eclipse中可以指定顺序,如果是在tomcat里运行,lib目录下一大堆的JAR包,怎么指定顺序啊?
再来做个实验,在CMD里,进入项目目录,手动使用java命令来执行这个class文件。
E:\workspace\test-using-which-one-jar>java -cp ./bin;./src/ac.jar org.test.TestM
ain
这是项目里的
先加载项目里的,后加载jar文件。
E:\workspace\test-using-which-one-jar>java -cp ./src/ac.jar;./bin org.test.TestM
ain
这是JAR文件里的
先加载JAR文件里的,后加载项目。
-cp参数用于指定classpath目录。到这里可以看出,为什么eclipse里可以指定顺序了吧。
如果是在tomcat里运行,lib目录下一大堆的JAR包,怎么指定顺序啊?