基於Lombok集成springboot遇到的坑

Lombok集成springboot遇到的坑

最近有同事在spring boot中用Lombok @Data註解時遇到瞭一個奇怪的問題,然後有幸一起研究瞭一下,把研究成果記錄下來。

問題

先上代碼:

@Data
public abstract class TestAbstract {
    private RedisTemplate redisTemplate;
    public TestAbstract(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }
}
@Data
public class TestChild extends TestAbstract {
    @Autowired
    public TestChild(RedisTemplate redisTemplate) {
        super(redisTemplate);
    }
}

上面的代碼在spring boot 2.0.2版本可以正常運行,但在2.0.3版本卻編譯錯誤。

Error:(13, 1) java: TestAbstract() 在 com.brotherj.learn.TestAbstract 中是private 訪問控制

查看瞭pom.xml文件後發現lombok的版本號是從spring boot繼承而來:

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

然後又查看瞭spring boot pom.xml中的lombok版本號,發現從spring boot 2.0.3版本開始使用瞭lombok 1.16.22,而2.0.2版本使用的是1.16.20版本。

#2.0.2
<lombok.version>1.16.20</lombok.version>

#2.0.3
<lombok.version>1.16.22</lombok.version>

於是修改pom.xml版本號之後,問題解決。

 <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
    <version>1.16.20</version>
</dependency>

原因

問題解決後,決定研究一下具體的原因,由於Lombok隻是依靠可插件化的Java自定義註解處理API(JSR 269: Pluggable Annotation Processing API)來實現在Javac編譯階段利用“Annotation Processor”對自定義的註解進行預處理後生成真正在JVM上面執行的“Class文件”。

所以應該時兩個版本下編譯生成的class文件不同,於是比較瞭一下兩個版本下編譯後的class文件。

    public TestAbstract(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }
    //1.16.22會生成一個private的構造方法,而1.16.20不會生成
    private TestAbstract() {
    }

     @Autowired
    public TestChild(RedisTemplate redisTemplate) {
        super(redisTemplate);
    }
    private TestChild() {
    }

看到這裡一切就都清楚瞭,是類加載順序導致的問題。

先復習一下類加載順序:(靜態變量、靜態初始化塊)–>(變量、初始化塊)–> 構造器。如果有父類,加載順序是:父類static方法 –> 子類static方法 –> 父類構造方法- -> 子類構造方法 。

也就是說,當加載TestChild類時先加載類TestAbstract的構造方法,而類TestAbstract的空參構造為private,於是報瞭訪問控制的錯誤。

springboot引入Lombok

傳統的寫法,要寫一串串的get()、set()方法等等

現引入Lombok

pom.xml引入

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>

引入後發現,在實體類上面使用@Data找不到import的包

網上巴拉巴拉,發現是springBoot的版本和import的版本不統一,加上

<optional>true</optional>

提示版本信息,改為可用的版本即可。修正後如下:

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
    <version>1.18.2</version>
</dependency>

終於可以正常導入^_^

延伸閱讀(1):

idea安裝Lombok插件

File——Settings——Plugins——Marketplact

延伸閱讀(2):

常見參數

  • @Setter 註解在類或字段,註解在類時為所有字段生成setter方法,註解在字段上時隻為該字段生成setter方法。
  • @Getter 使用方法同上,區別在於生成的是getter方法。
  • @ToString 註解在類,添加toString方法。
  • @EqualsAndHashCode 註解在類,生成hashCode和equals方法。
  • @NoArgsConstructor 註解在類,生成無參的構造方法。
  • @RequiredArgsConstructor 註解在類,為類中需要特殊處理的字段生成構造方法,比如final和被@NonNull註解的字段。
  • @AllArgsConstructor 註解在類,生成包含類中所有字段的構造方法。
  • @Data 註解在類,為類的所有字段註解@ToString、@EqualsAndHashCode、@Getter的便捷方法,同時為所有非final字段註解@Setter。

以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。

推薦閱讀: