参考
https://blog.csdn.net/mccand1234/article/details/60962283
在pom.xml 依赖jar包时,scope什么时候设置为provided。
<dependency>
<groupId>com.liferay.portal</groupId>
<artifactId>portal-impl</artifactId>
<version>6.1.0</version>
<scope>provided</scope>
</dependency>
依赖范围
maven中三种classpath编译,测试,运行
- compile
为默认的依赖有效范围
。如果在定义依赖关系的时候,没有明确指定依赖有效范围的话,则默认采用该依赖有效范围。此种依赖,在编译、运行、测试
时均有效。 - provided
在编译、测试
时有效,但是在运行时无效。例如:servlet-api,运行项目时,容器已经提供
,就不需要Maven重复地引入
。provided意味着打包的时候可以不用包进去,别的设施(Web Container)会提供。事实上该依赖理论上可以参与编译,测试,运行等周期。相当于compile,但是在打包阶段做了exclude的动作
。 - runtime
在运行、测试
时有效,但是在编译代码时无效。例如:JDBC驱动实现,项目代码编译只需要JDK提供的JDBC接口,只有在测试或运行项目时才需要实现上述接口的具体JDBC驱动。 - test:只在测试时有效
- system
在编译、测试
时有效,但是在运行时无效。和provided的区别是
,使用system范围的依赖时必须通过systemPath元素显式地指定依赖文件的路径
。由于此类依赖不是通过Maven仓库解析的,而且往往与本机系统绑定
,可能造成构建的不可移植
,因此应该谨慎使用。systemPath元素可以引用环境变量。例如:
<dependency>
<groupId>javax.sql</groupId>
<artifactId>jdbc-stdext</artifactId>
<version>2.0</version>
<scope>system</scope>
<systemPath>${java.home}/lib/rt.jar</systemPath>
</dependency>
传递依赖性
A–>B–>C。当前项目为A,A依赖于B,B依赖于C。知道B在A项目中的scope,那么怎么知道C在A中的scope呢?答案是:
当C是test或者provided时,C直接被丢弃,A不依赖C;
否则A依赖C,C的scope继承于B的scope。
scope取值 | 有效范围(compile, runtime, test) | 依赖传递 | 例子 |
---|---|---|---|
compile | all | 是 | spring-core |
provided | compile, test | 否 | servlet-api |
runtime | runtime, test | 是 | JDBC驱动 |
test | test | 否 | JUnit |
system | compile, test | 是 |
解释
对于scope=compile的情况(默认scope),也就是说这个项目在编译、测试、运行
阶段都需要
这个artifact(模块)对应的jar包在classpath中
。
而对于scope=provided的情况,则可以认为这个provided是目标容器已经provide这个artifact
。换句话说,它只影响到编译,测试阶段。在编译测试阶段,我们需要这个artifact对应的jar包在classpath中,而在运行阶段
,假定目标的容器(比如我们这里的liferay容器)已经提供了这个jar包
,所以无需我们这个artifact对应的jar包了
。
举例
比如说,假定我们自己的项目ProjectABC 中有一个类叫C1,而这个C1中会import这个portal-impl的artifact中的类B1,那么在编译阶段,我们肯定需要这个B1,否则C1通不过编译,因为我们的scope设置为provided了,所以编译阶段起作用,所以C1正确的通过了编译。测试阶段类似,故忽略。
那么最后我们要把ProjectABC部署到Liferay服务器上了,这时候,我们到$liferay-tomcat-home\webapps\ROOT\WEB-INF\lib下发现,里面已经有了一个portal-impl.jar了,换句话说,容器已经提供了这个artifact对应的jar
,所以,我们在运行阶段,这个C1类直接可以用容器提供的portal-impl.jar中的B1类,而不会出任何问题。
实际插件的行为
刚才我们讲述的是理论部分,现在我们看下,实际插件在运行时候,是如何来区别对待scope=compile和scope=provided的情况的。
做一个实验就可以很容易发现,当我们用maven install
生成最终的构件包ProjectABC.war
后,在其下的WEB-INF/lib
中,会包含被标注为scope=compile的构件的jar包
,而不会包含被标注为scope=provided的构件的jar包
。这也避免
了此类构件当部署到目标容器后产生包依赖冲突
。