最近看到Maven的依赖范围,之前的工作中一直在使用,但是其实并不是完全了解,查阅了很多资料,发现很多资料上介绍的都很模糊,没有具体的案例,因此写了两个module
测试不同范围的依赖有什么影响。
1. Maven依赖范围说明
项目依赖范围可以如下表:
依赖范围(Scope) | 对于编译classpath有效 | 对于测试calsspath有效 | 对于运行时classpath有效 | 说明 |
---|---|---|---|---|
compile | Y | Y | Y | 默认依赖范围,例子Spring-core |
test | - | Y | - | JUnit |
provided | Y | Y | - | Servlet-api |
runtime | - | Y | Y | JDBC驱动实现 |
system | Y | Y | - | 本地的,Maven仓库之外的类库文件 |
import | - | - | - | 通常用在dependencyManagement中 |
三种classpath可以分别理解为:
编译classpath: 代码的引用,也就是在src包下是否可以引用该代码
测试classpath: 测试引用,是都可以在单元测试用使用
运行classpath: 代码运行时可以引用,其他场景不能引用
2. 详细演示
2.1 compile说明
2.1.1 环境说明
假设有两个module,分别为module-a
和module-b
,module-b
依赖module-a
,
module-a
的pom依赖为
<groupId>com.marco</groupId>
<artifactId>module-a</artifactId>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.58</version>
<scope>provided</scope>
</dependency>
</dependencies>
module-a
中创建一个User类
public class User {
private Long id;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
module-b
的pom
文件为
<groupId>com.marco</groupId>
<artifactId>module-b</artifactId>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>com.marco</groupId>
<artifactId>module-a</artifactId>
<version>1.0.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>
</dependencies>
module-b
中的通过new方式创建对象演示代码
public class ModuleATest {
public static void main(String[] args) {
User user = new User();
user.setId(1L);
user.setName("小林同学");
System.out.println(user);
}
}
module-b
中的通过反射方式创建对象演示代码
public class ModuleAReflectTest {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class<?> userClass = Class.forName("com.marco.obj.User");
Constructor<?> constructor = userClass.getConstructor();
Object obj = constructor.newInstance();
System.out.println(obj);
}
}
2.1.2 运行结果
通过new方式创建对象运行结果正常
通过反射方式创建User对象运行结果正常
2.2 test说明
2.2.1 test环境配置
将module-b
对module-a
的依赖改成test
<groupId>com.marco</groupId>
<artifactId>module-b</artifactId>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>com.marco</groupId>
<artifactId>module-a</artifactId>
<version>1.0.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>
</dependencies>
2.2.2 运行结果
main方法中已经找不到了User
类了,说明编译classPath已经找不到这个类
test通过反射运行结果提示找不到类
test中的方法未报错
运行单元测试结果正常
通过上面测试代码印证了上表中的依赖范围
2.3 provided说明
2.3.1 provided环境说明
修改module-b
的pom依赖scope为provided
<groupId>com.marco</groupId>
<artifactId>module-b</artifactId>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>com.marco</groupId>
<artifactId>module-a</artifactId>
<version>1.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>
</dependencies>
2.3.2 运行结果
代码在idea是正常的,可以找到类
运行结果报错,提示找不到类,
这里我们把通过反射来创建User
单元测试结果是正常的,就不贴了
2.4 runtime说明
2.4.1 runtime环境说明
把module-b
的POM文件中依赖scope改成runtime
<groupId>com.marco</groupId>
<artifactId>module-b</artifactId>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>com.marco</groupId>
<artifactId>module-a</artifactId>
<version>1.0.0</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>
</dependencies>
2.4.2 运行结果
正常new对象提示找不到该类
通过反射得到的结果是正确的
测试结果也是正确的
2.6 import详细说明
import中的依赖范围不会对三种classpath产生实际的影响,一般只是用在dependencyManagement
中
3.总结
Maven的依赖范围最复杂的就是provided
和runtime
。
provided
常用于编译和测试项目的时候有效,在运行时无效的场景。例如servlet-api,编译和测试的时候需要该依赖,但项目运行的时候,容易会提供,因此不需要重复引入。
runtime
对于测试和运行的时候有效,但编译代码时无效。例如JDBC驱动实现,项目主代码中只需要提供JDBC接口,在测试运行时才需要实现具体的JDBC实现类。
其他依赖范围都相对简单,就不过多赘述了。
写了一天,各位大佬走过路过帮忙给个赞吧~~~
共同学习,写下你的评论
评论加载中...
作者其他优质文章