學習、工作心得分享-2018

2017一晃就過去了,忙碌的2017,可以說從來沒有這麼忙過了,部落格也忙的沒時間搭理。不過這忙碌的一年帶來太多太多的東西,技術從沒有過的突飛猛進,處理事情的能力和抗壓能力也得到提高。很開心這一年跟小夥伴們填坑、挖坑、抗雷。2018繼續,充實、快樂、鬧心、遭罪,就是幹!
這篇文章就說說2017年都得到了什麼吧!

一、技術

基礎

來了京東,真的理解了為啥面試要問spring BeanFactory和Factorybean的區別和多執行緒的知識。可能我們在日常開發中幾乎不會用到面試官問的東西,但是如果真的不理解這些東西,很容易寫出坑來。
下面我也丟擲很多問題,這裡不做詳細的解釋,如果你去了解這些並用到專案中,歡迎你來京東面試。

  • spring

    • spring中最常用的就是註解,面試了很多人,大部分不知道@Autowired和@Resource的區別是什麼,是很基礎簡單的東西。在我們開發的時候也會看到這兩種註解混用的時候。我想如果你的專案希望能好快速更換其他IOC容器的話,一定要用@Resource。
    • spring的BeanFactory和FactoryBean,記得幾年前我來京東面試的時候一個大神問的,至今我也會拿這個面試題去面試他人。雖然我們很少用FactoryBean,但經常會用BeanFactory。當你真的想定義一個自定義物件的時候,FactoryBean該粉墨登場了。
    • spring的生命週期和作用域,其實spring bean的生命週期挺難理解和記憶的,但是當你想要c 一樣的解構函式的時候,生命週期就得用上了。同時要知道spring物件的作用域,記得之前做一個專案的時候,因為bean使用預設的作用域的時候出現了併發問題。
    • 事務相關,spring的事務由兩種方式實現,一種aop的玩法攔截所有,一種宣告式事務,宣告式事務可以更細化,aop的玩法當然要會寫spel表示式。
    • AOP和IOC,不用多說了,我們最常用的就是這倆東西,京東的很多專案也都是拿AOP管理資料來源切換的。
  • 多執行緒(要多實踐!!!)

    • HashMap是不是執行緒安全的?不是,那麼如何讓它執行緒安全?Collections.synchronizedMap()與ConcurrentHashMap的區別?HashMap執行緒不安全的時候會出現什麼問題?這些是面試的時候必問的東西。如果你的專案請求量真的很大,需要全域性變數的時候同時很難設計出無鎖的演算法,那這些問題都是要面對的。HashMap 0.75是什麼?這關係到了你的程式效能。
    • 建立執行緒的三種方式都有什麼?Feature模式是什麼?教科書上只告訴我們了Thread和Runable。而最方便的恐怕是第三種了。
    • 執行緒池有幾種?如何建立一個自定義執行緒池,以及建構函式是什麼?當然回答肯定不是用commons-pool了。在京東某個子系統一天就能生產出上百萬條資料的情況下,使用執行緒池消費資料提高處理能力是很常見的。如果不知道執行緒池的這些東西,死定了。。。
    • 執行緒安全的實現方式,鎖:synchronized、ReentrantLock 無鎖:CAS、ThreadLocal等。如果設計了一個多執行緒的業務流程,不考慮執行緒安全造成了髒資料,資料量大,業務複雜修資料要熬夜通宵的!
  • 基礎語法
    • 列舉的好處和用法,最常用的就是在安全的單例模式上了。我們經常會給列舉一定的初始化值,然後在列舉類中編寫相關的查詢方法(getValueByCode、isXxx)來更方便的在外層呼叫,列舉值可以讓程式碼閱讀性更高。
    • static本質是什麼?為何要使用static?可以說static是個很方便的關鍵字,可以讓我們快速編寫工具類,也可以安全的初始化一些資料(要比建構函式安全)。靜態工廠方法取代建構函式,提高程式碼閱讀性。
    • final修飾在類上、變數上、方法上各自有什麼效果?我經常在mybatis的建立namespace上用到
      private static final String getNameSpace(final String method){ return NAME_SPACE "." method;}的寫法。這樣可以讓JIT進行inline method提高效能。而final在全域性變數中更會保證執行緒安全。
    • 深刻理解多型的本質,使用spring IOC ByName和lookup能夠快速進行實現類的切換,spring本身也是一種工廠模式的實現。利用這個特性在三方聯調的時候可以快速編寫mock物件。而對於DAO層可以注入基於redis、mysql、es的多種持久化實現,方便快速降級、提高擴充套件性等。
  • 設計模式

    • 單例:逢考必過,這東西跟寫氣泡排序一樣普及。當然會設計模式不是為了考試,很多請求量大要求QPS和實時性的系統通常不會使用spring或其他IOC容器來管理物件,因為那麼做系統會太臃腫犧牲的太多。每個請求不能都new一個業務物件,那麼如何寫好一個安全的單例模式(執行緒安全、效能高、防反射攻擊)都是要思考的。
    • 工廠:spring本身就是個大工廠,理解工廠模式就很好理解spring。當然工廠模式不是專門為spring準備的。我們有很多時候要自己寫個工廠建立物件,或者使用spring的FactoryBean。那麼三種工廠模式如何選擇?
    • 介面卡:其實這個模式我們經常用的到,仔細回想InputStream和OutputStream子類的使用方式。很多面試官也會問這個模式,當你真的理解這個模式的時候,編寫工具類會感覺很舒服。
    • 監聽者:其實監聽者不只侷限於程式設計中,我經常會問面試者訊息隊裡的本質是什麼?有的人會把mq伺服器的搭建包括cluster敘述一遍。但其實我的感覺本質就是監聽者模式。如果你的專案中沒必要用個非常強大的訊息佇列伺服器,而又非同步通訊時,你就可以用這個模式。
    • 策略:很工廠很像,很難區分,但要記住策略關注的是演算法。在近期的結算專案中和之前的差值率功能上,我多次使用策略模式,整合到spring中來實現不同業務的演算法。
    • 狀態:京東一個單據資料結構中通常會包含一些狀態欄位,而這些狀態欄位中也會有多種狀態(有的可能十幾種),如果你用十幾個if或者switch去做這件事,架構師一定會噴死你,我和我的小夥伴們經常在code review中被勸退重構這些if,用狀態模式重構。自然重構後的程式碼很難理解但很單一職責。
    • 責任鏈:我們經常使用責任鏈在web專案中,比如過濾字符集、引數和許可權校驗等。我們應該理解責任鏈的工作原理並且自己編寫一個責任鏈,這樣當我們不使用servlet或者第三方框架提供的過濾器的時候,程式碼依舊能夠那麼風騷,可以說:我們不一樣。
    • 建造者:一個領域物件(domain object 即DO)有幾十個屬性很正常,那麼如果一個一個寫setter&getter一定會累死,你可能說我們有編譯器自動生成工具。那你的呼叫者一定會很難看,new一個物件一堆set方法呼叫。試試builder,會讓呼叫者很舒服,可以看看protobuf的java實現,就是一個大大的build,呼叫起來很方便。
    • MVC:model-view-control,很經典而且很普及的模式,很基礎的模式,但是很多人會把業務程式碼寫在control中,職責混亂,在你改曾經某個被強姦了的control層痛苦難耐。我們有必要好好想想,mvc的本質是什麼?
  • 異常:

    • 使用自定義異常做業務異常處理(好處大大的),消滅所有非自定義異常(誰寫出空指標請吃冰激凌)!
    • 自定義異常編寫原則:繼承RuntimeException,重寫getMessage和getLocalizedMessage,getMessage可以返回詳細的異常棧資訊,getLocalizedMessage要返回識別度高的錯誤提示(用於前臺展示)。
    • try{}catch()中要處理Exception和業務異常,提供給呼叫者不同的體驗,Exception要記錄為系統異常,自定義異常要記錄為業務操作不當。
  • 工具類庫
    • apache commons:一定要使用StringUtils、CollectionUtils,這兩個類庫幾乎每天都要用,用於防禦式程式設計中,做好防禦程式設計bug會大面積減少。當然commons還有http、pool等功能。
    • guava:google提供的第三方工具類,包含了jvm內的本地快取、限流令牌桶的實現、lambda等功能。目前網際網路公司很多一級快取用的guava,二級快取使用的memcache或redis。
    • dozer:效能要比apache的BeanUtils高,而且可以通過xml定義要複製什麼屬性,同時避免了apache BeanUtils Date型別空拷貝時NPE的出現。整合spring很友好。
    • lombok:一個註解統一天下,在bean或者方法上加個小小的註解,再給編譯器安裝個外掛(idea和eclipse都有哦!),你可以很快得到一個builder模式或一百個屬性的setter&getter。當然還有執行緒安全、重寫toString、hashCode、equals等強大功能。
    • fastjson:alibaba總是為人類做出很大的貢獻。目前業內序列化和反序列化速度最快的json類庫,據說為了效能程式碼寫的很爛。一個字:屌!
    • druid:alibaba總是為人類做出很大的貢獻。提供了高效能的執行緒池,強大的sql監控功能。一個字:屌!
    • MBean:當你用到反射感覺這個技術很牛逼的時候,MBean其實更牛逼。一般人不知道。。。JMX的全稱為Java Management Extensions. 顧名思義,是管理Java的一種擴充套件。這種機制可以方便的管理、監控正在執行中的Java程式。常用於管理執行緒,記憶體,日誌Level,服務重啟,系統環境等。
    • junit&mock:保證程式碼沒bug一定是要大量做單元測試,其實京東的每個子系統都很龐大和複雜,很多專案都很古老了,我們在做一個簡單的讀取單據資訊可能就要對接很多系統。很多專案啟動的速度可能達到幾分鐘,而一些主要系統上線一次就要幾個小時。我們需要把程式碼寫到最優、bug儘量降低到0才能上線。單元測試複雜度高,兩種方案:
      1. 隨時重構:隨手重構,方法和類都要明確職責,單元測試到每個類的每個方法上,方法長度和類長度要控制。大量細小的方法和物件被測試成功,最終組合起來構成整個模組。
      2. mock測試:對接第三方系統很糟心,撕b常有。保證自己的程式碼沒問題除了記錄好的日誌,還有就是mock測試。mock測試保證了業務整體的正常運轉、消滅明顯的程式碼bug、資料傳輸的結構確定。同時能夠保證快速執行單元測試。
    • slf4j:一定要用slf4j,提高效能、更換日誌系統不用改程式碼。記得要用{}佔位符!
  • 框架(一定要看看常用框架的原始碼)
    • mybatis:使用mybatis的orm外,可以嘗試編寫它的外掛,interceptor能夠幫你坐很多事情(慢sql檢查、分頁)。
    • spring mvc:最簡單的一定要理解@RestController和@Controller的區別,問了好多面試者不知道這個。@RequestMapping註解中的每個屬性都很有用。spring mvc整體跟spring區別不大,本身就是spring社群周邊。核心還是理解好spring。
    • spring boot:有的人會直接去學習spring cloud,其實還是建議先學習spring mvc然後spring boot,最後可以選擇性的看看spring cloud。國內用spring cloud的目前很少,spring boot倒是挺多的,其實掌握了spring mvc對spring boot上手也快。記得一定要會自定義boot-starter和java config。
    • spring 社群:spring社群是指spring其他產品,比如spring data、spring ldap等。框架總是用的,拿來用主義,主要是學會spring社群的路子和精神,spring的template思想很值得借鑑。記得要會閱讀spring.io的doc。
    • dubbo:alibaba總是為人類做出很大的貢獻。java業內很普及的最近分散式服務框架,效能卓越,上手快(當然原理不簡單),dubbo的雙手甚至已經伸向了國外和其他程式語言上。dubbo又開始更新維護了,參加了一場dubbo的開發團隊的分享,他們也歡迎dubbo的社群貢獻者加入團隊。 一個字:屌!
    • jedis:redis的java sdk。每個redis的指令都會被對映為一個java方法。可以說我們會使用jedis,redis的指令基本也會了很多了。spring整合jedis很簡單,spring社群也推出了相關的框架。如果你能堅持閱讀jedis原始碼,那會對理解redis通訊協議很有幫助,包括它的cluster。
  • git(被忽略的技能,經常成為重災區,不多說,自己體會)
    • 還用svn多low b?看看靈魂擺渡人,鬼差都用iphone10s了,還不用國際流行的git?
    • 使用rebase
    • 讀懂reflog
    • 利用cherry-pick
    • 不要用圖形介面,這點很重要!
  • linux
    • 如果你能理解epoll、select、zero copy、sys和user空間、中斷,你非常好
    • 如果你會用top、vmstat、iostat、netstat、ping、telnet,你很好
    • 如果你會部署配置nginx、mysql、redis、haproxy、lvs,你真好
    • 如果你上面都不會,那最基本要會cd、ls、tail -f、rm、vi
    • 考一個rhce的認證,你能學到很多,如果你想挑戰,來個rhca

深入

  • jvm:jvm要說的太多,這是java的核心。如果你把jvm插的深一些,BAT不難進。推薦《深入理解java虛擬機器》、《java虛擬機器規範》、你假笨的公眾號。如果你會c/c ,一定要下載openJDK,自己去make一個虛擬機器,然後用source insight閱讀原始碼。經常對你的專案進行jvm層面調優,把你的編譯器修改jvm引數變得快快的。看看gclog和dump檔案,使用jprofile、mat去分析jvm。
  • redis:至少你應該知道redis的五種資料結構的用法,redis是單執行緒的,redis的pipeline事務,redis的鎖,redis實現分散式鎖方案,redis做session共享,redis防重,cluster是在客戶端實現的。更深入的可以閱讀《redis設計與實現》。
  • mysql:這年頭會寫sql語句不算啥,不會寫複雜的也沒啥(為了查詢效率,很多複雜語句要轉換成業務程式碼)。一定要知道explain怎麼用,一定要知道索引怎麼加,一定要會評估表空間和庫空間大小,一定要會選擇儲存引擎。如果你能說出innodb buffer pool的一些特性,最左原則,什麼語句寫法不會走索引,面試官一定會讓你過。《高效能mysql》、《mysql技術innodb儲存引擎》多看看。
  • mq:訊息佇列有很多實現,kafka、rabbitmq、activemq…層出不窮。但是還是一通百通。《RabbitMQ實戰:高效部署分散式訊息佇列》可以看看,雖然是python的。最起碼要知道mq兩個重要的作用:
    1. 解耦,消除異構系統、三方系統的差異最終解決方案,mq伺服器大多使用mqtt協議或自定義協議,但不同語言的sdk是可以直接對mq伺服器進行通訊的(協議統一化)。開發者不需要自定義協議。
    2. 消峰,十萬個請求要扣減一個商品的庫存,庫存只有十個,庫存不能超賣!沒錯這就是每年的6月18日全國各地敗家娘們乾的。棒棒只有十個,十萬的娘們含苞待放,先到先得五金一件,統統放入訊息隊裡中逐一處理,剩餘九萬九千九百九十個全滾回家睡覺去!
  • worker:定時任務通常會用linux系統的crontab、java的ScheduledExecutorService類自定義、Quartz服務、自定義TimerTask。而對於一些資料量大的需要快速消費掉資料,光憑多執行緒是很難提升消費能力的(畢竟是單機)。而分散式排程系統應該用上,京東有自己開發的clover,淘寶開源的tbschedule。worker其實實現不復雜,複雜與分散式一致性上,如果需要深入理解,可以讀讀paxos協議(挺複雜的,簡單點的是raft)或直接閱讀tbschedule原始碼。
  • Refactoring:重構,不是什麼工具也是個工具,不是工具是因為它是個技能,是個工具是因為重構手段能夠幫助你快速達到很多目的。單純的說讓你去重構,重構有多麼好是沒人會聽的,因為這種東西通常非常抽象並且教科書。如果你真的想提高自己的話,一定要看看《重構》、《程式碼整潔之道》這兩本書,老書經久不衰!通常很多設計模式也會用在重構上,如果《設計模式》這本書太枯燥,看看《大化設計模式》。

寫作(軟技能)

  • markdown,還用word多low b?看看靈魂擺渡人,鬼差都用iphone10s了,還不用國際流行的markdown?寫分享文章要用markdown!寫筆記要用markdown!寫說明書要用markdown!面試沒準考你markdown!
  • ppt,做好ppt,升職加薪沒問題!
    • 一個好的ppt一頁要控制在半分鐘到一分鐘
    • 一個好的ppt要拿資料說話,而不是特效和樣式
    • 一個好的ppt不要純文字!沒圖你說個xx?沒人會讀我這又臭又長的總結文章,我媳婦說的,她說的很對,真的很墨跡,湊字數沒幹貨,扯犢子Tree tree=new B();
    • 一個好的ppt末尾要簡單,一句話:感謝各位的聆聽!
  • blog
    • 寫blog提高你的總結能力;
    • 寫blog提高你的影響力;
    • 寫blog提高你的寫作能力;
    • 寫blog提高你的記憶力;
    • 寫blog new B();

二、職場

多想:慢點動手,慢點敲鍵盤,慢點想,想仔細,多想,想不到位自己遭罪!

少說:說錯了,得罪人!說多了,墨跡!說快了,沒禮貌!

多做:領導都看著呢,別偷懶,幹!當然,我們相信天道酬勤!

三、總結

2017真的很充實,很累,很快樂。從我不會做,到我做到了,這個過程真的很艱難。倆個雙十一,一個618,每次都是一種考驗,考驗自己的程式碼,考驗自己的心智,考驗自己的毅力。不斷的出錯、改正、優化,不斷的學習、思考、驗證。線上事故,程式碼bug,設計不合理,都發生過,就是因為這些,才充實,累,快樂。2018年,希望在我做到了再上一個臺階,我能獨當一面了。
這裡寫圖片描述