ZB-030-04Maven生命周期详解和插件配置

Spotbugs 自动化字节码bug检查工具

  • 它的前身叫做 findbugs ,但是很不幸的是从 java9以后就不维护了。
  • 它的后续叫做 Spotbugs

引入 Spotbugs

  • 打开链接 Spotbugs 官网
  • 找到 Using SpotBugs
    • 由于我们用的 maven构建 选择 maven
  • 直接复制它的例子代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <plugin>
    <groupId>com.github.spotbugs</groupId>
    <artifactId>spotbugs-maven-plugin</artifactId>
    <version>3.1.12</version>
    <dependencies>
    <!-- overwrite dependency on spotbugs if you want to specify the version of spotbugs -->
    <dependency>
    <groupId>com.github.spotbugs</groupId>
    <artifactId>spotbugs</artifactId>
    <version>4.0.0-beta3</version>
    </dependency>
    </dependencies>
    </plugin>
  • 继续看文档 spotbugs goal 意思是 “目标” 提示了一个 check命令

  • 然后到你的项目里 运行 mvn spotbugs:check,最后发现我们的代码 Build Success
  • 那就手写一个 bug ,在 main 方法里

    1
    2
    3
    4
    5
    6
    7
    8
    public static void main(String[] args) throws IOException {
    Integer i = null;
    if(i == 1){
    System.out.println();
    }
    }

    // 很明显会发生空指针异常
  • 再次运行mvn spotbugs:check 但是依然 Build Success

    • 这是因为,你没有给这个插件绑定一个阶段
    • 它分析的是字节码
  • 为 这个 spotbugs指定阶段 , 添加 executions

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    <plugin>
    <groupId>com.github.spotbugs</groupId>
    <artifactId>spotbugs-maven-plugin</artifactId>
    <version>3.1.12</version>
    <dependencies>
    <!-- overwrite dependency on spotbugs if you want to specify the version of spotbugs -->
    <dependency>
    <groupId>com.github.spotbugs</groupId>
    <artifactId>spotbugs</artifactId>
    <version>4.0.0-beta3</version>
    </dependency>
    </dependencies>
    <executions>
    <execution>
    <id>spotbugs</id>
    <phase>verify</phase>
    <goals>
    <goal>check</goal>
    </goals>
    </execution>
    </executions>
    </plugin>
  • 运行 mvn verify 此时给我们丢了一个错误出来

    1
    [ERROR] Null pointer dereference of i in com.github.hcsp.Main.main(String[]) [com.github.hcsp.Main] Dereferenced at Main.java:[line 23] NP_ALWAYS_NULL
  • 继续看 spotbugs 的文档 发现有个gui goal

    • 运行 mvn spotbugs:gui 会出现一个图形界面

一个刚刚的代码疑问

1
2
3
4
5
6
7
8
Integer i = null;
if(i == 1){
System.out.println();
}

// 其中
i == 1 会被处理成 i.equals(1) 吗?
如果你是写 java, 在 java中 == 永远不会自动变成 .equals()

Maven详解

它有一套生命周期 你可以搜索 maven lifecycle

  • 它会把这个生命周期的流程 从头到尾 执行一遍

这些生命周期的阶段会执行什么呢?

  • 默认情况什么都不做,除非你告诉它做什么

怎么告诉?通过另外一个机制

  • 插件 plugin
1
2
3
4
5
6
7
8
9
10
11
12
13
14
mvn
|validate |
| |
|... |
|compile--|--< 默认插件 maven-compiler-plugin
绑定到compile 阶段
于是执行此工作,这个工作叫做 goal 目标
| |
|test ---|--> surefile 官方测试插件 自动绑定到test阶段
| |
|... | 自定义插件 maven-checkstyle-plugin :
你可以指定绑定的阶段
| |
|verify |

自定义插件 指定阶段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
<plugin>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<configLocation>${basedir}/.circleci/checkstyle.xml</configLocation>
<includeTestSourceDirectory>true</includeTestSourceDirectory>
<enableRulesSummary>false</enableRulesSummary>
</configuration>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>com.puppycrawl.tools</groupId>
<artifactId>checkstyle</artifactId>
<version>8.22</version>
</dependency>
</dependencies>
</plugin>

重点看 execution
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
意思是 这个插件有个 goal 是 check ,阶段绑定在 compile 阶段
因此 maven运行在 compile阶段的时候,就知道要执行它

如果我绑定两个阶段呢?会先执行谁呢?
谁先声明的绑定谁

你还可以把它修改为 verify 阶段,这样 在 compile 阶段就不会执行它了
<execution>
<id>verify</id>
<phase>verify</phase>
<goals>
<goal>check</goal>
</goals>
</execution>

可不可以在 compile 和 verify 阶段都执行?
可以,只要你不觉得费劲,我们允许你做这么蛋疼的事情~~~
为什么允许这样呢? 因为你可以会在不同阶段传递不同的参数
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
<execution>
<id>verify</id>
<phase>verify</phase>
<goals>
<goal>check</goal>
</goals>
</execution>

当你执行 mvn verify时 会怎样?

  • 首先 maven 会从头把 lifecycle 的每个阶段从头执行到 verify阶段
  • 每当执行到每个阶段的时候,它会看看这个阶段有没有绑定某个插件的 目标 goal,如果有就执行,没有就什么都不做
  • 这就是 maven 标准,就是maven自动化