我有個學弟,在一家小型互聯網公司做Java後端開發,最近他們公司新來了一個技術總監,這位技術總監對技術細節很看重,一來公司之後就推出了很多"政策",比如定義了很多開發規範、日誌規範、甚至是要求大家統一使用某一款IDE。
但是這些都不是我這個學弟和我吐槽的點,他真正和我吐槽的是,他很不能理解,這位新來的技術總監竟然禁止公司內部所有開發使用Lombok。但是又沒給出十分明確的,可以讓人信服的理由。
於是他來找我聊天,問我這個要求到底是否合理。關於這個事情,我認爲這位技術總監的出發點是好的,但是做法未免有些極端。
之所以說出發點是好的,是因爲使用Lombok確實會帶來很多問題,而且我個人在工作中也基本不主動使用。
之所以說不主動使用,那是因爲有些同事的代碼還是使用了的,所以我也被迫的要安裝Lombok的插件。
既然聊到這個話題,就簡單說說我的一些看法。
Lombok有什麼好處?
Lombok是一款非常實用Java工具,可用來幫助開發人員消除Java的冗長代碼,尤其是對於簡單的Java對象(POJO)。它通過註釋實現這一目的。
如果大家對於Lombok比較瞭解的話,可以先跳過這一段,直接往後看,如果不是很熟悉的話,可以簡單瞭解一下。
想在項目中使用Lombok,需要三個步驟:
一、IDE中安裝Lombok插件
目前Lombok支持多種IDE,其中包括主流的Eclips、Intellji IDEA、Myeclipse等都是支持的。
二、導入相關依賴
Lombok 支持使用多重構建工具進行導入依賴,目前主要支持maven、gardle、ant等均支持。
如使用maven導入方式如下:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
三、代碼中使用註解
Lombok精簡代碼的方式主要是通過註解來實現,其中常用的有@Data、@Getter/@Setter、@Builder、@NonNull等。
如使用@Data註解,即可簡單的定義一個Java Bean:
import lombok.Data;
@Data
public class Menu {
private String shopId;
private String skuMenuId;
private String skuName;
}
使用@Data註解在類上,相當於同時使用了@ToString、@EqualsAndHashCode、@Getter、@Setter和@RequiredArgsConstrutor這些註解,對於POJO類十分有用。
即自動幫忙給例子中的Menu類中定義了toString、Getter、Setter等方法。
通過上面的例子,大家可以發現,我們是使用@Data註解大大減少了代碼量,使代碼非常簡潔。這也是很多開發者熱衷於使用Lombok的主要原因。
另外,關於Lombok的使用,不同人有不同的看法,因爲很多人都使用過Lombok,對於他的優點都比較瞭解,所以接下來我們重點說一下Lombok的使用會帶來哪些問題。
Lombok有什麼壞處?
強X隊友
因爲Lombok的使用要求開發者一定要在IDE中安裝對應的插件。
如果未安裝插件的話,使用IDE打開一個基於Lombok的項目的話會提示找不到方法等錯誤。導致項目編譯失敗。
也就是說,如果項目組中有一個人使用了Lombok,那麼其他人就必須也要安裝IDE插件。否則就沒辦法協同開發。
更重要的是,如果我們定義的一個jar包中使用了Lombok,那麼就要求所有依賴這個jar包的所有應用都必須安裝插件,這種侵入性是很高的。
代碼可讀性,可調試性低
在代碼中使用了Lombok,確實可以幫忙減少很多代碼,因爲Lombok會幫忙自動生成很多代碼。
但是這些代碼是要在編譯階段纔會生成的,所以在開發的過程中,其實很多代碼其實是缺失的。
在代碼中大量使用Lombok,就導致代碼的可讀性會低很多,而且也會給代碼調試帶來一定的問題。
比如,我們想要知道某個類中的某個屬性的getter方法都被哪些類引用的話,就沒那麼簡單了。
有坑
因爲Lombok使代碼開發非常簡便,這就使得部分開發者對其產生過度依賴。
在使用Lombok過程中,如果對於各種註解的底層原理不理解的話,很容易產生意想不到的結果。
舉一個簡單的例子,我們知道,當我們使用@Data定義一個類的時候,會自動幫我們生成equals()方法 。
但是如果只使用了@Data,而不使用@EqualsAndHashCode(callSuper=true)的話,會默認是@EqualsAndHashCode(callSuper=false),這時候生成的equals()方法只會比較子類的屬性,不會考慮從父類繼承的屬性,無論父類屬性訪問權限是否開放。
這就可能得到意想不到的結果。
影響升級
因爲Lombok對於代碼有很強的侵入性,就可能帶來一個比較大的問題,那就是會影響我們對JDK的升級。
按照如今JDK的升級頻率,每半年都會推出一個新的版本,但是Lombok作爲一個第三方工具,並且是由開源團隊維護的,那麼他的迭代速度是無法保證的。
所以,如果我們需要升級到某個新版本的JDK的時候,若其中的特性在Lombok中不支持的話就會受到影響。
還有一個可能帶來的問題,就是Lombok自身的升級也會受到限制。
因爲一個應用可能依賴了多個jar包,而每個jar包可能又要依賴不同版本的Lombok,這就導致在應用中需要做版本仲裁,而我們知道,jar包版本仲裁是沒那麼容易的,而且發生問題的概率也很高。
破壞封裝性
以上幾個問題,我認爲都是有辦法可以避免的。但是有些人排斥使用Lombok還有一個重要的原因,那就是它會破壞封裝性。
衆所周知,Java的三大特性包括封裝性、繼承性和多態性。
如果我們在代碼中直接使用Lombok,那麼他會自動幫我們生成getter、setter 等方法,這就意味着,一個類中的所有參數都自動提供了設置和讀取方法。
舉個簡單的例子,我們定義一個購物車類:
@Data
public class ShoppingCart {
//商品數目
private int itemsCount;
//總價格
private double totalPrice;
//商品明細
private List items = new ArrayList<>();
}
//例子來源於《極客時間-設計模式之美》
我們知道,購物車中商品數目、商品明細以及總價格三者之前其實是有關聯關係的,如果需要修改的話是要一起修改的。
但是,我們使用了Lombok的@Data註解,對於itemsCount 和 totalPrice這兩個屬性。雖然我們將它們定義成 private 類型,但是提供了 public 的 getter、setter 方法。
外部可以通過 setter 方法隨意地修改這兩個屬性的值。我們可以隨意調用 setter 方法,來重新設置 itemsCount、totalPrice 屬性的值,這也會導致其跟 items 屬性的值不一致。
而面向對象封裝的定義是:通過訪問權限控制,隱藏內部數據,外部僅能通過類提供的有限的接口訪問、修改內部數據。所以,暴露不應該暴露的 setter 方法,明顯違反了面向對象的封裝特性。
好的做法應該是不提供getter/setter,而是隻提供一個public的addItem方法,同時取修改itemsCount、totalPrice以及items三個屬性。
總結
本文總結了常用的Java開發工具Lombok的優缺點。
優點是使用註解即可幫忙自動生成代碼,大大減少了代碼量,使代碼非常簡潔。
但是並不意味着Lombok的使用沒有任何問題,在使用Lombok的過程中,還可能存在對隊友不友好、對代碼不友好、對調試不友好、對升級不友好等問題。
最重要的是,使用Lombok還會導致破壞封裝性的問題。
雖然使用Lombok存在着很多方便,但是也帶來了一些問題。
但是到底建不建議在日常開發中使用,我其實保持一箇中立的態度,不建議大家過度依賴,也不要求大家一定要徹底不用。
只要大家在使用的過程中,或者評估要不要在代碼中引入Lombok之前,在想到它的優點的同時,能夠考慮到他給代碼帶來的問題的,那麼本文的目的也就達到了!
小編整理出一篇Java進階架構師之路的核心知識,同時也是面試時面試官必問的知識點,篇章也是包括了很多知識點,其中包括了有基礎知識、Java集合、JVM、多線程併發、spring原理、微服務、Netty 與RPC 、Kafka、日記、設計模式、Java算法、數據庫、Zookeeper、分佈式緩存、數據結構等等
由於pdf文檔裏的細節內容實在過多所以只編輯了部分知識點的章節粗略的介紹下,每個章節小節點裏面都有更細化的內容!以下就是部分章節目錄,由於頭條的篇幅限制目錄上的詳細講解也無法一一列出,文末底下有獲取以下章節的所有詳細知識講解。
JVM
- 線程
- JVM內存區域
- JVM運行時內存
- 垃圾回收與算法
- JAVA 四中引用類型
- GC分代收集算法 VS 分區收集算法
- GC垃圾收集器
- JAVA IO/NIO
- JVM 類加載機制
由於篇幅限制小編,細節內容實在太多啦,所以只把部分知識點截圖出來粗略的介紹,每個小節點裏面都有更細化的內容!有需要的程序猿(媛)可以幫忙轉發+關注私信(架構資料)獲取哦
JAVA集合
- 接口繼承關係和實現
- List
- ArrayList(數組)
- Vector(數組實現、線程同步)
- LinkList(鏈表)
- Set
- HashSet(Hash表)
- TreeSet(二叉樹)
JAVA多線程併發
- JAVA併發知識庫
- JAVA線程實現/創建方式
- 4種線程池
- 線程生命週期(狀態)
- 終止線程4種方式
- sleep與wait 區別
- start與run區別
- JAVA後臺線程
- JAVA鎖
- 線程基本方法4.1.11. 線程上下文切換
- 同步鎖與死鎖
- 線程池原理
- JAVA阻塞隊列原理
- CyclicBarrier、CountDownLatch、Semaphore的用法
- volatile關鍵字的作用(變量可見性、禁止重排序)
- 如何在兩個線程之間共享數據
JAVA基礎
- JAVA異常分類及處理
- JAVA反射
- JAVA註解
- JAVA內部類
- JAVA泛型
- JAVA序列化(創建可複用的Java對象)
- JAVA複製
Spring 原理
- Spring 特點
- Spring 核心組件
- Spring 常用模塊
- Spring 主要包
- Spring 常用註解
- Spring第三方結合
- Spring IOC原理
- Spring APO原理
- Spring MVC原理
- Spring Boot原理
- JPA原理
- Mybatis緩存
- Tomcat架構
由於篇幅限制小編,細節內容實在太多啦,所以只把部分知識點截圖出來粗略的介紹,每個小節點裏面都有更細化的內容!有需要的程序猿(媛)可以幫忙轉發+關注私信(架構資料)獲取哦
微服務
- 服務註冊發現
- API 網關
- 配置中心
- 事件調度(kafka)
- 服務跟蹤(starter-sleuth)
- 服務熔斷(Hystrix)
- Hystrix斷路器機制
- API管理
Netty 與RPC
- Netty 原理
- Netty 高性能
- Netty RPC實現
- 關鍵技術
- 核心流程
- 消息編解碼
- 通訊過程
- RMI實現方式
分佈式緩存
- 緩存雪崩
- 緩存穿透
- 緩存預熱
- 緩存更新
- 緩存降級
網絡
- 網絡7層架構
- TCP/IP原理
- TCP三次握手/四次揮手
- HTTP原理
- CDN 原理
- 分發服務系統
- 負載均衡系統
- 管理系統
日誌
- Slf4j
- Log4j
- LogBack
- Logback優點
- ELK
Zookeeper
- Zookeeper概念
- Zookeeper角色
- Zookeeper工作原理(原子廣播)
- Znode有四種形式的目錄節點
Kafka
- Kafka概念
- Kafka數據存儲設計
- partition的數據文件(offset,MessageSize,data)
- 數據文件分段segment(順序讀寫、分段命令、二分查找)
- 數據文件索引(分段索引、稀疏存儲)
- 生產者設計
- 負載均衡(partition會均衡分佈到不同broker上)
- 批量發送
- 壓縮(GZIP或Snappy)
- 消費者設計
RabbitMQ
- RabbitMQ概念
- RabbitMQ架構
- Exchange 類型
Hbase
- Hbase概念
- 列式存儲
- Hbase核心概念
- Hbase核心架構
- Hbase的寫邏輯
- HBase vs Cassandra
- MongoDB
- MongoDB概念
- MongoDB特點
Cassandra
- Cassandra概念
- 數據模型
- Cassandra一致Hash和虛擬節點
- Gossip協議
- 數據複製
- 數據寫請求和協調者
- 數據讀請求和後臺修復
- 數據存儲(CommitLog、MemTable、SSTable)
- 二級索引(對要索引的value摘要,生成RowKey)
- 數據讀寫
設計模式
- 設計原則
- 工廠方法模式
- 抽象工廠模式
- 單例模式
- 建造者模式
- 原型模式
- 適配器模式
- 裝飾器模式
- 代理模式
- 外觀模式
- 橋接模式
- 組合模式
- 享元模式
- 策略模式
- 模板方法模式
- 觀察者模式
- 迭代子模式
- 責任鏈模式
- 命令模式
- 備忘錄模式
負載均衡
- 四層負載均衡 vs 七層負載均衡
- 負載均衡算法/策略
- LVS
- Keepalive
- Nginx反向代理負載均衡
- HAProxy
數據庫
- 存儲引擎
- 索引
- 數據庫三範式
- 數據庫是事務
- 存儲過程(特定功能的SQL 語句集)
- 觸發器(一段能自動執行的程序)
- 數據庫併發策略
- 數據庫鎖
- 基於Redis分佈式鎖
- 分區分表
- 兩階段提交協議
- 三階段提交協議
- 柔性事務
- CAP
一致性算法
- Paxos
- Zab
- Raft
- NWR
- Gossip
- 一致性Hash
- 一致性Hash特性
- 一致性Hash原理
JAVA算法
- 二分查找
- 冒泡排序算法
- 插入排序算法
- 快速排序算法
- 希爾排序算法
- 歸併排序算法
- 桶排序算法
- 基數排序算法
- 剪枝算法
- 回溯算法
- 最短路徑算法
- 最大子數組算法
- 最長公共子序算法
- 最小生成樹算法
數據結構
- 棧(stack)
- 隊列(queue)
- 鏈表(Link)
- 散列表(Hash Table)
- 排序二叉樹
- 紅黑樹
- B-TREE
- 位圖
加密算法
- AES
- RSA
- CRC
- MD5
Hadoop
- Hadoop概念
- HDFS
- Client
- NameNode
- Secondary NameNode
- DataNode
- MapReduce
- JobTracker
- TaskTracker
- Task
- Reduce Task 執行過程
- Hadoop MapReduce 作業的生命週期
- 作業提交與初始化
- 任務調度與監控。
- 任務運行環境準備
- 任務執行
- 作業完成
Spark
- Spark概念
- 核心架構
- 核心組件
- SPARK編程模型
- SPARK計算模型
- SPARK運行流程
- SPARK RDD流程
- SPARK RDD
Storm
- Storm概念
- 集羣架構
- Nimbus(master-代碼分發給Supervisor)
- Supervisor(slave-管理Worker進程的啓動和終止)
- Worker(具體處理組件邏輯的進程)
- Task
- ZooKeeper
- 編程模型(spout->tuple->bolt)
- opology運行
- Storm Streaming Grouping
- ResourceManager
- NodeManager
- ApplicationMaster
- YARN運行流程
雲計算
- SaaS
- PaaS
- IaaS
- Docker
- Openstack
- Namespaces
- 進程(CLONE_NEWPID 實現的進程隔離)
- Libnetwork與網絡隔離
- 資源隔離與CGroups
- 鏡像與UnionFS
- 存儲驅動
由於篇幅限制小編,pdf文檔的詳解資料太全面,細節內容實在太多啦,所以只把部分知識點截圖出來粗略的介紹,每個小節點裏面都有更細化的內容!有需要的程序猿(媛)可以幫忙轉發+關注私信(架構)獲取哦
如何獲取免費架構學習資料?
資料獲取方式:
關注+轉發後,私信關鍵詞 【資料】即可免費獲取到!
重要的事情說三遍,轉發、轉發、轉發後再發私信,纔可以拿到!
重要的事情說三遍,轉發、轉發、轉發後再發私信【資料】,就可以免費拿到!