懷舊框架集合
最近在公司用JUP框架做項(xiàng)目,發(fā)現(xiàn)這個(gè)框架是別人基于SpringSide封裝的,所以打算學(xué)習(xí)下,SpringSide,其中遇到了很多坑,做個(gè)記錄,網(wǎng)上關(guān)于這方面的資料都有些老了,而且SpringSide最新的版本是SpringSide-Utils,老一點(diǎn)的版本為v4.2.2.GA,以下分別對(duì)這兩個(gè)版本分別介紹下,主要內(nèi)容來(lái)自于網(wǎng)上。
一些資料:
Github源碼地址: https://github.com/springside/springside4
OSchina源碼地址: https://git.oschina.net/calvin1978/springside4
官方文檔: https://github.com/springside/springside4/wiki
SpringSide網(wǎng)址: http://springside.github.io/
1、SpringSide簡(jiǎn)介
SpringSide--Pragmatic Enterprise Application KickStart and Common Library Stack,這么長(zhǎng)的一個(gè)名字下來(lái),不用解釋大家都知道是做什么的了----以Spring Framework為core,提供一個(gè)Pragmatic的企業(yè)應(yīng)用開(kāi)發(fā)基礎(chǔ)以及企業(yè)應(yīng)用中各主題的最佳實(shí)踐展示。
愿景:為使用Spring框架的開(kāi)發(fā)者提供一個(gè)非Demo版的復(fù)雜、正式而體現(xiàn)最佳使用實(shí)踐的參照系統(tǒng)。為JavaEEer必須面對(duì)的問(wèn)題提供合乎Pragmatic原則的解決方案。
SpringSide的四個(gè)部分--
Springside-Bookstore: 一個(gè)Full Feature的書(shū)店示例,兼有書(shū)店前臺(tái)和后臺(tái)管理,作為典型企業(yè)應(yīng)用的微縮版。
SpringSide-Core :SpringSide封裝的核心代碼。
SpringSide-Templates: 讓用戶(hù)可以快速?gòu)?fù)制粘貼構(gòu)建出自己應(yīng)用的代碼模版,分Application與Plugins兩部分。
SpringSide-Generator: 自動(dòng)整合SpringSide-Application/Plugins生成項(xiàng)目,生成CRUD代碼的Eclipse Plugins 和Ant 腳本。
來(lái)看看SpringSide的作者,江南白衣的對(duì)它的介紹:
SpringSide是什么?為什么要發(fā)起這個(gè)項(xiàng)目?
SpringSide是以Spring Framework為核心的,Pragmatic風(fēng)格的JavaEE應(yīng)用參考示例,是Java世界中的主流技術(shù)選型,最佳實(shí)踐的總結(jié)與演示。因?yàn)榛赟pring也因?yàn)閷?duì)Spring理念的認(rèn)同,項(xiàng)目起名SpringSide,另外還有個(gè)好記的中文名字——“春天的旁邊”。
想起做這個(gè)項(xiàng)目,是在六七年前元旦輾轉(zhuǎn)反側(cè)的夜晚,想著自己應(yīng)該為世界留下點(diǎn)什么。寫(xiě)一本書(shū)還是做一個(gè)開(kāi)源項(xiàng)目呢? 總感覺(jué)書(shū)印出來(lái)了就沒(méi)法改了,對(duì)我這種完美主義者有點(diǎn)難受。而開(kāi)源項(xiàng)目,就可以永遠(yuǎn)年輕,永遠(yuǎn)生長(zhǎng),永遠(yuǎn)重構(gòu)……
然后,做什么項(xiàng)目呢?那時(shí)候,淘寶們還沒(méi)有開(kāi)始大規(guī)模開(kāi)源自己的技術(shù)。國(guó)內(nèi)的原創(chuàng)框架更多是在自?shī)首詷?lè)。所以SprinSide選了一條更低端的路線,將那時(shí)候已經(jīng)太多而不是太少的開(kāi)源項(xiàng)目粘合在一起,用好,也算是一樁功德了。
SpringSide包含哪些演示項(xiàng)目? 這些項(xiàng)目采用或演示了哪些技術(shù)?
SpringSide里含有QuickStart 與 Showcase 一小一大兩個(gè)示例項(xiàng)目。
QuickStart是一個(gè)迷你的TodoList應(yīng)用,濃縮了一個(gè)普通JavaEE應(yīng)用所需的柴米油鹽各種基礎(chǔ)技術(shù),從典型的CRUD界面,到趕時(shí)髦的Rest API,以及最基礎(chǔ)的用戶(hù)管理功能,可以作為很多項(xiàng)目的初始骨架。
Showcase 則一個(gè)五花八門(mén)的JavaEE技術(shù)大雜燴大派對(duì),如安全、緩存、日志、消息中間件、定時(shí)任務(wù)等等等等。
SpringSide 4和之前版本相比,有哪些較大改進(jìn)?
SSH 與 SSH2 發(fā)展到高潮后,Spring也進(jìn)入了一個(gè)后Spring的時(shí)代,受到各種新興語(yǔ)言與框架如Play! Framework的圍攻。SpringSide 4,演示的就是這個(gè)后Spring時(shí)代的演進(jìn),如何使得avaEE依然是個(gè)體面的選擇。
一些變動(dòng)包括 DAO框架轉(zhuǎn)用Spring Data JPA + Hibernate, MVC框架轉(zhuǎn)用Spring MVC 3, Restful框架轉(zhuǎn)用Spring MVC + Spring RestTemplate, CSS框架轉(zhuǎn)用Twitter Bootstrap,安全框架轉(zhuǎn)用Apache Shiro 等等,Selenium升級(jí)到WebDriver。
所有變動(dòng)的目標(biāo),都是在代碼越來(lái)越簡(jiǎn)單的同時(shí),也保持對(duì)工業(yè)化大規(guī)模開(kāi)發(fā)的支持。比如有些新興語(yǔ)言框架,高手自己可以寫(xiě)得很快,但不一定適合很多普通程序員一起合作開(kāi)發(fā)與維護(hù)。所以有些過(guò)度簡(jiǎn)化的演進(jìn),比如完全拋棄XML純用Annotation的ApplicationContext定義方式,SpringSide并沒(méi)有使用。
如何基于SpringSide創(chuàng)建新的項(xiàng)目?
SpringSide也是利用Maven的Archetype插件來(lái)創(chuàng)建新項(xiàng)目的,在每次版本發(fā)布時(shí)都會(huì)把前面所說(shuō)的QuickStart項(xiàng)目打包成一個(gè)模板項(xiàng)目。用戶(hù)只要用標(biāo)準(zhǔn)的maven archetype指令,就可以基于QuickStart項(xiàng)目生成自己的項(xiàng)目。
SpringSide采用什么開(kāi)源協(xié)議?對(duì)商用有什么限制?
用的是所知最開(kāi)放的Apache License2,任何的Copy&Paste都是歡迎的。如果有哪個(gè)更開(kāi)放的告訴我吧,因?yàn)閷?shí)在對(duì)靠開(kāi)源賺錢(qián)沒(méi)有過(guò)任何想法。
有沒(méi)有其他開(kāi)發(fā)者參與貢獻(xiàn)?
4.0這個(gè)大版本暫時(shí)只有我一個(gè)在主導(dǎo)。不過(guò)github真的是一個(gè)非常社交化的開(kāi)源平臺(tái),沒(méi)有了sourceforge、google code那種固定的開(kāi)發(fā)團(tuán)隊(duì)的概念。現(xiàn)在誰(shuí)都可以闖進(jìn)SpringSide來(lái),改它幾行代碼,然后向我發(fā)起一個(gè)Pull Request就可以了。題外話,像Nutz那樣精細(xì)的貢獻(xiàn)者記錄,真是值得表?yè)P(yáng)又讓人羨慕的事情。
SpringSide的發(fā)布周期?未來(lái)的發(fā)展方向?
項(xiàng)目堅(jiān)持了六七年,四個(gè)大版本,期間服務(wù)器遷徙數(shù)次,也有過(guò)多次跳票的不良記錄。所以很難說(shuō)出一個(gè)固定的發(fā)布周期來(lái)。最近自己比較希望能做到與白天的項(xiàng)目一樣,固定三周一個(gè)的迭代,但也并不總能如愿。希望大家能相信我的人品,項(xiàng)目或遲或早,總是會(huì)發(fā)布的……
至于未來(lái)的發(fā)展方向,一方面會(huì)繼續(xù)做細(xì)JavaEE普通應(yīng)用的演示,使它與一般的玩具型演示項(xiàng)目有更顯眼的區(qū)別。一方面會(huì)展示更多互聯(lián)網(wǎng)項(xiàng)目的新潮技術(shù),如NoSQL、ZooKeeper等,畢竟這看起來(lái)更有趣。
2、SpringSide4技術(shù)選型
以下是對(duì)SpringSide-Utils的一個(gè)簡(jiǎn)單介紹:
1.SpringSide-Utils簡(jiǎn)介
把在唯品會(huì)兩年的實(shí)踐抽取出來(lái),做一個(gè)大大大的公共類(lèi)庫(kù)。一邊封裝 Guava 和 Apache Common Lang,一邊參考移植各門(mén)各派的精華:
專(zhuān)門(mén)的類(lèi)庫(kù):Jodd, Apache Common IO,Common Collections,JCTool,OpenHFT,AndroidUtilCode
大廠的開(kāi)源類(lèi)庫(kù):Facebook JCommon,twitter commons,linkedin-utils
內(nèi)庫(kù)中包含了文本、數(shù)字、日期、并發(fā)、集合、文件、反射、安全等方面的內(nèi)容等著大家一一探索,這里又再?lài)Z叨一下性能,性能,性能。
新庫(kù)的設(shè)計(jì)目標(biāo),是把最佳實(shí)踐都封裝起來(lái),讓大家使用類(lèi)庫(kù)時(shí),默認(rèn)就獲得最優(yōu)的性能。
2.日期
2.1 DateFormatUtil
日期與String相互轉(zhuǎn)換時(shí),JDK的SimpleDateFormat,又慢,又非線程安全。
在不能全面轉(zhuǎn)為Joda Time時(shí),使用Common Lang的FastDateFormat,又快,又線程安全,還能緩存實(shí)例。
2.2 CachingDateFormatter
FastDateFormat再快,日期格式化還是個(gè)消耗很大的事情。
參考Logback和Log4j2,在打印當(dāng)前時(shí)間的場(chǎng)景里,將同一時(shí)刻的結(jié)果緩存。
3. 文本
3.1 StringBuilderHolder
ThreadLocal地重用StringBuilder,節(jié)約長(zhǎng)字符串拼接時(shí)的內(nèi)存消耗,節(jié)約成倍復(fù)制擴(kuò)容的CPU消耗,是OpenHFT等好幾個(gè)類(lèi)庫(kù)的共同選擇。
3.2 HashUtil
ThreadLocal地重用SHA1的MessageDiggest,減少每次創(chuàng)建MessageDigest的消耗,也是Tomcat,F(xiàn)acebook等好幾個(gè)類(lèi)庫(kù)的共同選擇。
3.3 JsonMapper
封裝Jackson的實(shí)現(xiàn),并提供不序列化“值為NULL的屬性”等選擇。
3.4 TextValidator
判斷是否合法的電話,身份證之類(lèi)的正則表達(dá)式校驗(yàn),Pattern必須得預(yù)先編譯而不要每次創(chuàng)建,但總有匆忙的同學(xué)忘記這點(diǎn)。
3.5 MoreStringUtil
Common Lang的StringUtils已經(jīng)很好用了。不過(guò)字符串操作的消耗總是很大,這里針對(duì)一些操作,給出更極致的性能優(yōu)化,比如split()。
4. 集合
4.1 原子類(lèi)型集合
當(dāng)集合中的元素是原子類(lèi)型,而不是對(duì)象的時(shí)候。直接以原子類(lèi)型來(lái)存儲(chǔ),不但節(jié)約內(nèi)存(int vs Integer, 4 bytes vs 16 bytes),甚至內(nèi)部的數(shù)據(jù)結(jié)構(gòu)也能完全不一樣,從而大幅提高性能。
從Netty中移植了IntOjbectHashMap 和 LongObjectHashMap,性能約提升50%。后面還會(huì)有IntArrayList等等。
4.2 MapUtil, ListUtil ...
各種集合類(lèi)的Util的創(chuàng)建函數(shù),強(qiáng)迫大家去思考Array Base 集合類(lèi)的初始大小,避免了容量不足時(shí)的成倍擴(kuò)容; HashMap的加載因子,減少哈希沖突。
在集合為空或只有一個(gè)元素時(shí),使用Java Collections的特殊數(shù)據(jù)結(jié)構(gòu),進(jìn)一步節(jié)約內(nèi)存。
4.3 其他擴(kuò)展類(lèi)型
1. Guava
MuitlSet :as MapCounter,不用再自己處理“如果有就+1,沒(méi)有就放個(gè)元素進(jìn)去”的煩事
MultiMap: as MultiValueMap
WeakConcurrentHashMap: 鍵值為弱引用的并發(fā)Map,只此一家
RangeMap:定義一段范圍的Key,對(duì)應(yīng)一個(gè)Value,類(lèi)似一致性哈希環(huán)之類(lèi)的最合適
2. Common Collections:
UniqueArrayList
MultiKeyMap
Flat3Map:如果少于3個(gè)元素直接訪問(wèn)屬性,否則才訪問(wèn)真正的HashMap
3. Jodd
SortedArrayList
4. JCTools
針對(duì) “多個(gè)生產(chǎn)者一個(gè)消費(fèi)者”, “一個(gè)生產(chǎn)者多個(gè)消費(fèi)者” 等特定場(chǎng)景優(yōu)化的Queue。
5. 并發(fā)
5.1 JSR166e
JDK的不同版本,不斷推出性能更優(yōu)的并發(fā)實(shí)現(xiàn),但如果考慮多JDK版本到的兼容就讓人發(fā)愁了。好在有Doug Lea大神的JSR166e項(xiàng)目。
1. ThreadLocalRandom
Random本身有全局鎖,JDK7的ThreadLocalRandom通過(guò)在ThreadLocal里放Random避免了鎖。
2. LongAdder
作為計(jì)數(shù)器,AtomicLong雖然能通過(guò)CAS避免鎖,但如果線程競(jìng)爭(zhēng)激烈時(shí)依然有很大的損耗。JDK8的LongAdder,根據(jù)并發(fā)情況,將計(jì)數(shù)器智能的拆開(kāi)成若干個(gè),等取值時(shí)再求和。
3. ConcurrentHashMapV8
JDK5開(kāi)始的ConcurrentHashMap是經(jīng)典的分散鎖模式,而JDK8的ConcurrentHashMap,優(yōu)化后居然取消了鎖。
5.2 ThreadPoolBuilder
比JDK Executors,提供更好的線程池設(shè)置,比如FixedPool的隊(duì)列最大長(zhǎng)度,CachedPool的最大線程數(shù)等。
另提供一個(gè)從Tomcat移植的QueueableCachedPool,“支持可變的線程數(shù),跑滿線程時(shí)任務(wù)放隊(duì)列”這種符合大家想想的場(chǎng)景。
5.3 ThreadLocalContext
提供ThreadLocal HashMap存放上下文的示例,并給出更高效的,使用EnumMap的建議。
6. 反射
6.1 BeanMapper
基于orika封裝,同時(shí)避免了一些低效API的使用,比如不給出來(lái)源集合的類(lèi)型,讓框架自己去反射"iterator"函數(shù)的返回值來(lái)獲取類(lèi)型的惡劣行為。
更給出了預(yù)生成Type類(lèi)型的最高效的用法。
6.2 FastMethodInvoker
基于cglib,通過(guò)代碼生成實(shí)現(xiàn)最快速的反射調(diào)用。比如反射調(diào)用A類(lèi)的“hello” 方法,它就直接生成一個(gè)調(diào)用a.hello()的FastMethod子類(lèi).
7. 其他
7.1 ExceptionUtil
異常構(gòu)造時(shí),獲取當(dāng)前Stack Trace是一個(gè)很耗時(shí)的過(guò)程,把Stack Trace打印也同樣消耗。
如果是一個(gè)比較清楚出處的異常,可以通過(guò)static定義的靜態(tài)異常。
但如果異常的message會(huì)變化,就不能靜態(tài)定義唯一的異常了,此時(shí)可使用克隆異常,依然避過(guò)構(gòu)造函數(shù)。
7.2 SystemPropertiesUtil
Properties本質(zhì)上是一個(gè)有鎖的HashTable,所以不能頻繁的調(diào)用System.getProperty()。提供了一個(gè)以回調(diào)方式獲取變化的ListenableProperties。
posted on 2020-10-09 19:14 paulwong 閱讀(312) 評(píng)論(0) 編輯 收藏 所屬分類(lèi): SPRING