小心Lombok用法中的坑
剛才寫完了代碼,自測的時候,出現了NPE問題。
排查的時候發現是Lombok的坑,以前也遇到過,所以覺得有必要過來記錄一下。
我先描述一下現象,我的代碼里面訂單服務A 需要調用緩存服務B,服務B就是一個Bean,使用方式是這樣的:
class?ServiceA?{//使用?Lombok?提供的setter@Setterprivate?ServiceB?bXCacheService;public?Data?getData()?{//這里出現了NPE問題bXCacheService.getSomeThing();}? }這個問題使用Lombok 的同學可能有人遇到過,我用的是螞蟻的Sofa,Spring也是類似的,
先說下bean初始化過程,是通過反射,調用set 方法初始化bean,下面代碼是我截取的部分代碼:Spring 中的初始化bean方法
public?void?setValue(final?Object?object,?Object?valueToApply)?throws?Exception?{//獲取write方法,實際就是setXXX方法final?Method?writeMethod?=?this.pd.getWriteMethod();if?(!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())?&&?!writeMethod.isAccessible())?{if?(System.getSecurityManager()?!=?null)?{AccessController.doPrivileged(new?PrivilegedAction<Object>()?{@Overridepublic?Object?run()?{writeMethod.setAccessible(true);return?null;}});}?else?{writeMethod.setAccessible(true);}}final?Object?value?=?valueToApply;if?(System.getSecurityManager()?!=?null)?{}?else?{//?通過反射?用set?方法注入屬性writeMethod.invoke(getWrappedInstance(),?value);} }問題就出在 Sofa 拼接 bean 變量 set 方法的方式,例如:如果我們希望初始化的 bean 名稱為 cacheService,那么 Sofa 拼接的 set 方法為 setCacheService,也就是set + 變量(首字母大寫+剩余字符)。
但是如果 bean 名稱是:tCacheService,bean 首字母小寫,第二次字符是大寫,那 set 方法就變成了:settCacheService,當第二個字符是大寫的時候,set 不會設置變量 t 為大寫 T。
但是 Lombok 不是這樣,Lombok 的setter注解實現機制,會讓 tCacheService 的 setter 方法變成 setTCacheService(), 所以bean初始化的時候會找不到 WriteMethod,bean注入失敗,報NPE問題。
解決方法
解決方法要么調整bean的命名方式,不要讓第二個字符是大寫,要么改變這種變量不使用Lombok 注入,使用Idea / Eclipse 生成的setter 方法。
也算是Lombok 和 Idea 生成 setter 方法的區別,一般框架、中間件更偏向 Idea 的這種set 變量方式。
另一個需要注意的問題
還有一個不只是Lombok 要注意的點,就是boolean 類型的變量嚴禁使用 is 開頭,因為無論是Lombok 還是Idea 默認生成的get 方法都是is打頭,丟掉多余的is,set方法去掉is,可能引發非預期的問題,例如變量 boolean isOpen 和 變量 boolean open 變量的get方法名是一樣的:isOpen(); set 方法都是 setOpen(boolean isOpen);
private?boolean?isOpen;public?boolean?isOpen()?{return?isOpen; }public?void?setOpen(boolean?open)?{isOpen?=?open; }常規編程規范里面會讓返回值是 boolean 變量的方法名以 is開頭,但是變量本身不帶is。
//?開火開關??--?集中參數中心配置項 private?String?fireSwitch;?public?boolean?isOpenFire()?{return?StringUtils.equalsIgnoreCase(?"TRUE",?fireSwitch); }往期推薦Java中List排序的3種方法!
面試官:元素排序Comparable和Comparator有什么區別?
面試官:HashSet是如何保證元素不重復的?
總結
以上是生活随笔為你收集整理的小心Lombok用法中的坑的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SpringCloud Ribbon中的
- 下一篇: Java夺命21连问!(附答案)