Maven dependency Summary: maven dependency
I. Scope of dependency
Maven uses a set of classpath when compiling the main code of the project. Second, another classpath is used during compilation and execution of the test. Finally, a set of classpath is used when the Maven project is run.
The so-called dependency scope is used to control the relationship between dependencies and the three classpath (compilation, testing, and running). Maven has the following dependency scopes:
- Compile: Compile the dependency scope. If not specified, this dependency range is used by default. This dependency range is valid for compilation, testing, and running. For example, spring-core must be used for compiling, testing, and running.
- Test: Test the dependency scope. Valid only for test classpath. For example, JUnit is only required when compiling the test code and running the test. This dependency cannot be used when compiling and running classpath.
- Provided: The dependency scope is provided. It is valid for compilation and testing, but not for runtime. For example, servlet-api requires this dependency during project compilation and testing. However, during runtime, Maven does not need to be repeatedly introduced because the container has already provided it.
- Runtime: Runtime dependency. Invalid during compilation, effective for testing and running. For example, for JDBC driver implementation, only the JDBC interface provided by JDK is required during compilation. The specific JDBC driver for the above interface must be implemented only when testing and running are performed.
- System: System dependency scope. Same as provided. When using this dependency, you must explicitly specify the dependency file path through the systemPath element. It is mainly used to depend on local class library files that are not in the Maven repository. For example:
<dependency> <groupId>javax.sql</groupId> <artifactId>jdbc-stdext</artifactId> <version>2.5</version> <scope>system</scope> <systemPath>${spath}/lib/test.jar<systemPath></dependency>
Ii. Passing dependencies and scope of Dependencies
When we depend on. jar, if. jar depends on B. jar, you only need to declare. jar dependency, B. jar is automatically loaded by Maven.
For example, there is a dependency of org. springframework: spring-core: 2.5.6. In fact, spring-core also has its own dependency, which depends on commons-logging. With the transfer dependency mechanism, you do not need to consider what it depends on when using spring-core. Maven automatically parses the file.
The dependency scope changes slightly when the dependency is passed.
When the range of the second direct dependency is compile, the scope of the passed dependency is consistent with that of the first direct dependency;
When the range of the second direct dependency is test, the dependency will not be passed;
When the range of the second direct dependency is provided, only the dependency of the first direct dependency is also provi, And the range is provided;
When the range of the second direct dependency is runtime, the passed dependency range is the same as that of the first direct dependency, but the compile exception is that the passed dependency range is runtime;
Iii. Mediation
- Principle 1: the most recent path is preferred. For example, if A-> B-> C-> X (1.0) and A-> D-> X (2.0) at the same time, it is clear that the path X (2.0) is shorter, will be used for parsing.
- Principle 2: The first speaker is preferred. When the dependency length is equal, resolve the pre-test order in the dependency declaration in pom. For example, A-> B-> X (1.0) and A-> D-> X (2.0 ). If B declares before D, X (1.0) will be parsed.
In addition to the preceding two principles, you can also manually exclude them, for example, A-> B-> X (1.0) and A-> X (2.0 ). If project A wants to load X (2.0), the following declaration can be made, and the <exclusion> element is used to explicitly exclude it.
<dependency> <groupId>com.xxx.xx</groupId> <artifactId>xx-B</artifactId> <version>2.5</version> <exclusions> <exclusion> <groupId>com.xx</groupId> <artifactId>project-X</artifactId> </exclusion> </exclusions></dependency><dependency> <groupId>com.xxx.xx</groupId> <artifactId>project-x</artifactId> <version>2.0</version></dependency>
4. Optional Dependencies
Example: B. jar is A persistent layer toolkit that supports both Mysql and PostgreSql. Project A depends on Project B. jar, the driver of these two databases is required when building A, but it depends on one type of database when used. Project A's dependency declaration is as follows:
<Dependency>
<GroupId> com. xxx. xx </groupId>
<ArtifactId> xx. db </artifactId>
<Version> 2.5 </version>
<Dependencies>
<Dependency>
<GroupId> mysql </groupId>
<ArtifactId> mysql-connector-java </artifactId>
<Version> 5.1.10 </version>
<Optional> true </optional>
</Dependency>
<Dependency>
<GroupId> postgresql </groupId>
<ArtifactId> postgresql </artifactId>
<Version> 8.4-701. jdbc3 </version>
<Optional> true </optional>
</Dependency>
</Dependencies>
</Dependency>
Use the <optional> element to indicate that the two are optional dependencies, which are not transmitted to project A. When project A needs to use A MySQL-based database, the dependency on mysql needs to be explicitly declared.
In addition, this is not ideal, because in object-oriented design, there is a single responsibility principle, that is, a jar should have only one responsibility. Therefore, for B. jar, it is best to create two Maven projects to implement mysql and postgresql respectively.
V. Dependency Optimization
Code must be constantly restructured to achieve the optimal performance. The same is true for dependency management. Redundant dependencies must be removed and necessary dependencies must be explicitly declared.
Maven automatically parses the direct dependencies and transmits dependencies of all projects, and determines the scope of each dependency based on rules. It can also adjust some dependency conflicts, after these tasks, you can obtain the complete resolved dependencies of the project.
You can run the following command to view the resolved dependencies of the current project:
mvn dependency:list
Demonstrate all resolved dependencies in the current project, and the scope of each dependency is clearly indicated.
If the dependency declared directly in pom is defined as the first-level dependency, and the dependency of these top-level dependencies is defined as the second-level dependency, a complete dependency tree can be formed accordingly.
You can run the following details to view the dependency tree of the current project.
mvn dependency:tree
It can be clearly seen that although there is no declared slf4j-api, it is loaded by passing dependencies, and its range is compile.
Run the following command to analyze the dependencies of the current project
Used undeclared dependencies in, which indicates that the dependencies Used in the project are not explicitly declared. We can see that the first dependency is the SNAPSHOT version, which is loaded by passing dependencies. This dependency is a hidden and potential bomb in the project, because it references a non-stable version of SNAPSHOT, it is easily ignored because it is not explicitly declared in pom. Once the bomb explodes, it often takes a lot of time to find out.
There is also an Unused declared dependencies, indicating the dependency that is not used in the project but explicitly declared. If not, we recommend that you remove the declaration. However, it should be noted that dependency: analyze will analyze the dependencies required for compilation and testing, and some runtime dependencies cannot be found. Therefore, be careful when optimizing dependencies.