Happy Moment
I want to buy a motorcycle, but I don't have enough money. I want to borrow some from my dad.
Me: Dad, I want to buy a motorcycle, it's easy to commute to work.
Dad: Your cousin fell off his motorcycle last month, don't you know? You still want to buy a motorcycle?
Me: I'm sorry, I'm not buying
Boss: That's right, just ride your cousin's car, why buy a new one?
Let's start with a question.
with respect tomaven
The dependence of the (dependency
I'm sure we all know a little bit about it.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="/POM/4.0.0"
xmlns:xsi="http:///2001/XMLSchema-instance"
xsi:schemaLocation="/POM/4.0.0 /xsd/maven-4.0.">
<modelVersion>4.0.0</modelVersion>
<groupId></groupId>
<artifactId>spring-boot-2_7_18</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId></groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.18</version>
</parent>
<properties>
<>8</>
<>8</>
<>UTF-8</>
</properties>
<dependencies>
<dependency>
<groupId></groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
Isn't it reasonable and logical to introduce whatever you depend on? Let's take a look at thelog
dependencies
I used idea's Maven Helper plugin, a good maven dependency analysis tool.
At this point, are you in doubt: don't you just rely on thespring-boot-starter-web
How come there's all kinds oflog
of dependence?
And then I'm in Add a line in the middle, just add a line
at this timelog
Dependency has changed from what it was before.
What's this for?
You think it doesn't matter, but the following exception occurs when you actually start it (see the cause:SpringBoot2.7 or capricious, just does not support Logback1.3, you can do anything about it!)
SLF4J: Failed to load class "org.".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http:///#StaticLoggerBinder for further details.
Exception in thread "main" : org/slf4j/impl/StaticLoggerBinder
at (:304)
at (:118)
at (:238)
at (:220)
at (:178)
at (:171)
at (:145)
at (:133)
at (:79)
at $starting$0(:56)
at (:1249)
at (:120)
at (:56)
at (:299)
at (:1300)
at (:1289)
at (:16)
Caused by: : org.
at (:381)
at (:424)
at $(:331)
at (:357)
... 17 more
And then you're confused.
Let's tweak it.
at this timelog
Relies on the following
Maybe that's okay with you guys, I'll quote it again for you;logback1.3.14
dependentslf4j
The version is2.0.7
then (in that case)slf4j1.7.36
Where is it from and why isn't it2.0.7
?
With this barrage of questions down, I'm asking if you're panicking, but don't you panic, because I'm going to make a move!
transferential dependence
Before the birth of maven, adding jar dependencies can be a big headache, you need to manually add all the jars, it is easy to miss, and then according to the exceptions to make up for the missing jar; many experienced veterans will be categorized, such as the introduction of Spring need to add which several jars, the introduction of the POI need to add which several jars, but it is still easy to miss; while the maven pass-through dependency mechanism is a good solution to this problem. maven's pass-through dependency mechanism solves this problem very well
What is transitive dependence, going back to our original case
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="/POM/4.0.0"
xmlns:xsi="http:///2001/XMLSchema-instance"
xsi:schemaLocation="/POM/4.0.0 /xsd/maven-4.0.">
<modelVersion>4.0.0</modelVersion>
<groupId></groupId>
<artifactId>spring-boot-2_7_18</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId></groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.18</version>
</parent>
<properties>
<>8</>
<>8</>
<>UTF-8</>
</properties>
<dependencies>
<dependency>
<groupId></groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
Intuitively it looks like it only relies on thespring-boot-starter-web
Libyan Arab Jamahiriyaspring-boot-starter-web
also has its own dependencies, which maven resolves, and so on. maven introduces those necessary indirect dependencies into the current project as pass-through dependencies
concern
not rely on
spring-boot-starter-web
How come there's all kinds oflog
of dependence?
Is it clear?
Dependency Priority
The pass-through dependency mechanism greatly simplifies dependency declarations and is very developer-friendly. For example, if we need to use spring's web functionality, we can simply introduce the
<dependency>
<groupId></groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
It's ok, isn't it so easy? But there are some problems, for example, project P has two transitive dependencies as follows
P -> A -> B -> C(1.0)
P -> D -> C(2.0)
So which C will be introduced into the P project by maven? At this point, maven enables its first principle
Shortest path first
Here.trails
refers to the length of the pass dependency, a pass dependency has a length of 1, a P to C (1.0) pass dependency has a length of 3, and a P to C (2.0) pass dependency has a length of 2. Therefore, C (2.0) will be introduced by maven into the P project, while C (1.0) will be ignored
Shortest path first
does not solve all problems, for example, project P has two transitive dependencies as follows
P -> B -> C(1.0)
P -> D -> C(2.0)
The length of both passed dependencies is 2, so who does maven bring in? Starting with maven 2.0.9, maven adds the second principle
Priority of the first statement
processShortest path first
If B is declared before D, then C(1.0) will be introduced to P by maven and C(2.0) will be ignored.
Let's look at it again.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="/POM/4.0.0"
xmlns:xsi="http:///2001/XMLSchema-instance"
xsi:schemaLocation="/POM/4.0.0 /xsd/maven-4.0.">
<modelVersion>4.0.0</modelVersion>
<groupId></groupId>
<artifactId>spring-boot-2_7_18</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId></groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.18</version>
</parent>
<properties>
<>8</>
<>8</>
<>UTF-8</>
<>1.3.14</>
</properties>
<dependencies>
<dependency>
<groupId></groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
The logback at this point
Why 1.3.14 and not 1.2.12, which actually involvesCustom Properties
which is somewhat similar to override in java; 1.2.12 is a custom property declared in a parent dependency (spring-boot-starter-parent) of a parent dependency (spring-boot-dependencies) of the
And the custom attributes we declare ourselves<>1.3.14</>
Just in time to cover it.1.2.12
So maven uses1.3.14
Is that the last question? Let's review the question, which reads as follows
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="/POM/4.0.0"
xmlns:xsi="http:///2001/XMLSchema-instance"
xsi:schemaLocation="/POM/4.0.0 /xsd/maven-4.0.">
<modelVersion>4.0.0</modelVersion>
<groupId></groupId>
<artifactId>spring-boot-2_7_18</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId></groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.18</version>
</parent>
<properties>
<>8</>
<>8</>
<>UTF-8</>
<>1.3.14</>
</properties>
<dependencies>
<dependency>
<groupId></groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-logging</artifactId>
<groupId></groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId></groupId>
<artifactId>logback-classic</artifactId>
<version>${}</version>
</dependency>
</dependencies>
</project>
Dependency at this time
Why is slf4j 1.7.36 and not 2.0.7 in logback?Custom Properties
prioritization
The prioritization of custom attributes follows the same first and second principles of maven dependency passing
Inherited from grandpa (spring-boot-dependencies) be
1.7.36
is equivalent to its own, the length of the pass dependency is 0, and logback inherits it from its parent (2.0.7)
The pass dependency length is 1, so maven uses the1.7.36
rather than2.0.7
The easiest way to change it is as follows
<properties>
<>8</>
<>8</>
<>UTF-8</>
<>1.3.14</>
<>2.0.7</>
</properties>
summarize
-
maven's dependency passing is a very powerful feature, so don't wonder if you've ever had a situation where you've introduced one dependency and brought in too many.
-
maven dependency prioritization follows two principles
First principle: shortest path first
Second principle: precedence of the first statement
The second principle is applied only in cases handled by the first principle; custom attributes also follow these two principles