真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

如何用Java反射提高開發(fā)效率的框架

本篇內(nèi)容介紹了“如何用Java反射提高開發(fā)效率的框架”的有關(guān)知識(shí),在實(shí)際案例的操作過程中,不少人都會(huì)遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

在源匯等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場(chǎng)前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供網(wǎng)站制作、做網(wǎng)站 網(wǎng)站設(shè)計(jì)制作定制網(wǎng)站,公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),品牌網(wǎng)站制作,營銷型網(wǎng)站建設(shè),外貿(mào)網(wǎng)站建設(shè),源匯網(wǎng)站建設(shè)費(fèi)用合理。

基于spring的aop,定義一個(gè)注解做為切點(diǎn),注釋在service層的分頁查詢方法上,聲明方法的返回結(jié)果POJO對(duì)象的哪個(gè)字段需要應(yīng)用默認(rèn)值規(guī)則。

通過aop在方法執(zhí)行完成之后,給返回結(jié)果應(yīng)用配置的默認(rèn)值規(guī)則,再返回給前端,如下圖所示。


 

如何用Java反射提高開發(fā)效率的框架


 

如果一次查詢返回含有20個(gè)元素的數(shù)組List,要對(duì)每個(gè)元素R都反射查找一次Field,判斷該Field的值,如果為空則賦值為默認(rèn)值,那就是重復(fù)做反射獲取Field,亂用反射,延長接口的響應(yīng)時(shí)間。


 

對(duì)于默認(rèn)值規(guī)則應(yīng)用這個(gè)例子,我們可以有很好的做法,拿到R類中的name字段,即Field,只需要反射一次。就是在應(yīng)用啟動(dòng)時(shí),執(zhí)行包掃描獲取到R的Class對(duì)象,執(zhí)行反射獲取R類型中所有的Field,然后使用Map>緩存在內(nèi)存中,這樣用到的時(shí)候就能很快拿到。雖然會(huì)消耗點(diǎn)內(nèi)存,但這是可以忽略的,因?yàn)檎麄€(gè)系統(tǒng)應(yīng)用到默認(rèn)值規(guī)則的類就沒幾個(gè)。


 

我認(rèn)為我設(shè)計(jì)的這套默認(rèn)值規(guī)則是最優(yōu)的方案。

1、使用aop實(shí)現(xiàn)代碼的解耦,默認(rèn)值規(guī)則的應(yīng)用邏輯不侵入業(yè)務(wù)代碼,隨時(shí)可對(duì)這個(gè)功能進(jìn)行插拔。


 

2、同時(shí),利用反射可以實(shí)現(xiàn)添加默認(rèn)值規(guī)則不需要改動(dòng)任何代碼,隨時(shí)添加隨時(shí)用,隨時(shí)修改隨時(shí)生效。


 

3、再者,由于默認(rèn)值規(guī)則存在的很少改動(dòng)這個(gè)特性,使用內(nèi)存緩存,有效減少數(shù)據(jù)庫的查詢次數(shù),也是對(duì)性能的一個(gè)提升。


 

…………… 利用反射提高工作效率  …………  


 

業(yè)務(wù)場(chǎng)景簡介  


 

今天,我繼續(xù)分享另一種反射的使用場(chǎng)景,包括如何設(shè)計(jì)實(shí)現(xiàn)。以此,回答本篇文章開頭的問題,怎樣才算用到刀刃上。


 

先了解點(diǎn)簡單的業(yè)務(wù)場(chǎng)景,這段內(nèi)容主要介紹使用場(chǎng)景,看不懂沒關(guān)系,大概過一遍就行。


本次優(yōu)化的是一個(gè)定時(shí)任務(wù)服務(wù),它要做的就是調(diào)用很多第三方的接口拉取數(shù)據(jù),并轉(zhuǎn)為平臺(tái)統(tǒng)一結(jié)構(gòu)的數(shù)據(jù),如將A、B、C…轉(zhuǎn)為P,存入到數(shù)據(jù)庫中。


假如我有一個(gè)產(chǎn)品,需要做推廣,那我就是上游廣告主,而我想投放到百度搜索、微信朋友圈展示,那么百度和微信就是下游渠道。但中間可能經(jīng)過幾層渠道,而中間的每一個(gè)渠道對(duì)于下游來說都是一個(gè)廣告主,也都可以稱為網(wǎng)盟平臺(tái),大家可能會(huì)對(duì)百度網(wǎng)盟廣告平臺(tái)有所耳聞。



如何用Java反射提高開發(fā)效率的框架


那么作為一個(gè)網(wǎng)盟平臺(tái),需要整合上游的Offer,批給下游去展示。整合上游的 Offer就是調(diào)用每個(gè)上游提供的api。但每個(gè)上游所返回的json數(shù)據(jù)都不一樣,字段名稱也不一樣。那就需要為每個(gè)api實(shí)現(xiàn)一個(gè)解析映射的方法。這就是重復(fù)勞動(dòng)。如何減少這種重復(fù)勞動(dòng),就是提高工作效率。


簡單一句話,要做什么


與Mybatis實(shí)現(xiàn)的將查詢結(jié)果映射成pojo對(duì)象的過程相似。如果還覺得這段內(nèi)容抽象,那就直接跳過吧,我改了好幾次,發(fā)現(xiàn)都好難表述清楚啊。


解析映射,就是將json數(shù)據(jù)解析后得到的java對(duì)象Response,之后,再獲取到Response中存放廣告信息數(shù)組(List)的字段的值,再遍歷該List,將每個(gè)元素由類型A轉(zhuǎn)為平臺(tái)統(tǒng)一的類型對(duì)象B,這個(gè)過程就是A to B,比如。


class A{

        String a_name;

}


Class B{

       String name;

}


實(shí)現(xiàn) A==>to ==> B 就是:

A a;

B b;

b.setName(a.getA_name());


很顯然,直接使用反射copy字段的值是沒有用的,一是字段名不同,二是可能字段的類型也不同,三是還可能是下面這樣情況。


class A{

       C c;

      public static class C{

              String c_name;

       }

}


 

class B{

       String name;

}


實(shí)現(xiàn) A==>  to ==> B 就是:

A a;

B b;

b.setName(a.getC().get C_name());


如何實(shí)現(xiàn)自動(dòng)映射


如果可以添加一個(gè)注解,在注解中聲明映射規(guī)則,比如其中一條:class A中的name字段對(duì)應(yīng)class B中的pkgName字段。


如果能根據(jù)注解聲明的一個(gè)個(gè)映射規(guī)則,完成自動(dòng)映射,就可以不用每次都寫這些重復(fù)代碼了。是的,我要實(shí)現(xiàn)的就是這樣一個(gè)功能。


P.S:最后我還加入了插件功能,滿足一些需要做特殊處理的需求。


類結(jié)構(gòu)樹的定義


知道我為啥叫它結(jié)構(gòu)樹嗎?二叉樹不是二叉樹,n差數(shù)不是n叉樹,我不懂怎么叫,難道這是我自己發(fā)明的?哈哈。


以一個(gè)例子來講,不那么抽象。如圖,實(shí)現(xiàn)自動(dòng)從TestResponse對(duì)象中,拿到List rowset的值。因?yàn)楦鶕?jù)對(duì)接文檔,我知道這個(gè)字段正是廣告Offer集合,一個(gè)item代表一個(gè)廣告Offer。


如何用Java反射提高開發(fā)效率的框架  


要實(shí)現(xiàn)根據(jù)注解自動(dòng)將TestResponse對(duì)象解析生成List集合,那肯定要對(duì)TestResponse對(duì)象的結(jié)構(gòu)了如指掌(下文將這一類由調(diào)用API返回的對(duì)象稱為Response對(duì)象)。所以需要將TestResponse類中的字段信息映射成一顆樹。


先不講那么多,來看下最終實(shí)現(xiàn)的效果,使用@ProdCampaignMapRules注解聲明映射規(guī)則。


如何用Java反射提高開發(fā)效率的框架  



正如上圖所示,我在RowsetBean類添加@ProdCampaignMapRules注解,意味著會(huì)自動(dòng)將類型為RowsetBean的對(duì)象,映射生成ProdCampaign對(duì)象。


認(rèn)真看,你會(huì)發(fā)現(xiàn),TestRsponse類上面還有個(gè)注解@MapRulesComponent,它的作用只是聲明這個(gè)類支持使用自動(dòng)映射。我在程序啟動(dòng)時(shí),會(huì)掃描所有被該注解注釋的Response,將這些Response解析成一棵棵類結(jié)構(gòu)樹,緩存在內(nèi)存中。


實(shí)現(xiàn)自動(dòng)解析API返回的廣告Offer數(shù)組,映射生成平臺(tái)統(tǒng)一的ProdCampaign集合的步驟,繼續(xù)以上圖中的例子為例。


第一步:從類結(jié)構(gòu)樹中,找到有@ProdCampaignMapRules的ClassNode,再得到這個(gè)ClassNode 所屬的FieldNode。找到的FieldNode就是Response中的List rowset字段。獲取rowset的值,這就得到了廣告Offer集合。


第二步:New一個(gè)List,遍歷廣告Offer集合rowset,將每個(gè)RowsetBean類型的元素轉(zhuǎn)為平臺(tái)統(tǒng)一的ProdCampaign對(duì)象,并添加到List集合中。


第三步:將每個(gè)RowsetBean轉(zhuǎn)為ProdCampaign的過程當(dāng)中,需要new一個(gè)ProdCampaign對(duì)象,然后給這個(gè)對(duì)象里面的字段賦值。值從哪來?從RowsetBean對(duì)象中找到與之對(duì)應(yīng)的字段,并獲取值,為ProdCampaign對(duì)象賦值。很好理解,不就是屬性拷貝。


第四步:如果是多層映射,如例子中的“offer.name"映射規(guī)則,就是要先獲取到RowsetBean對(duì)象中的offer字段,類型為OfferBean。再繼續(xù)下一層name的映射,name的映射就是獲取OfferBean的name字段。這就是一個(gè)兩層映射的例子。


我定義的結(jié)構(gòu)體看起來很復(fù)雜。RuleMetaData,就是完成包掃描后每個(gè)Class生成的類結(jié)構(gòu)樹。類中的字段信息用FieldNode存放,如果該字段的類型是非基本數(shù)據(jù)類型,則FieldNode的child是該字段所對(duì)應(yīng)類型的ClassNode數(shù)據(jù)。


如何用Java反射提高開發(fā)效率的框架

整棵結(jié)構(gòu)樹就是一個(gè)RuleMetaData,根節(jié)點(diǎn)root肯定是一個(gè)ClassNode。非基本數(shù)據(jù)類型的FieldNode也有一個(gè)child指向一個(gè)ClassNode。很抽象?沒關(guān)系,繼續(xù)看,下面會(huì)有一張圖,形象的畫出了這棵結(jié)構(gòu)數(shù)。


實(shí)現(xiàn)包掃描將Class解析成一顆結(jié)構(gòu)樹


在應(yīng)用啟動(dòng)時(shí),實(shí)現(xiàn)包掃描,找出所有被@MapRulesComponent注釋的類,解析生成結(jié)構(gòu)樹RuleMetaData,舉個(gè)例子。



如何用Java反射提高開發(fā)效率的框架

如圖,已經(jīng)畫得很形象了,這棵樹的結(jié)構(gòu)應(yīng)該已經(jīng)在你的腦子里。

結(jié)構(gòu)樹的root節(jié)點(diǎn),是該Response的第一個(gè)字段,存儲(chǔ)了這個(gè)字段的字段名和反射獲取到的Field,所屬類TestResponse。下個(gè)字段就是節(jié)點(diǎn)的nextField字段,由于該字段的類型是基本數(shù)據(jù)類型int,所以child的值為null。

到data字段的時(shí)候,由于其類型是非基本數(shù)據(jù)類型,而是一個(gè)內(nèi)部類DtaBean,需要解析成一個(gè)ClassNode,同時(shí)要繼續(xù)反射取得DataBean的所有字段的FieldNode節(jié)點(diǎn)鏈。最后將data節(jié)點(diǎn)的child指向這個(gè)ClassNode。

在反射DataBean生成FieldNode鏈的時(shí)候,處理到rowset字段,發(fā)現(xiàn)其是一個(gè)List類型,那就獲取這個(gè)List的元素的類型,這個(gè)反射是支持的,能獲取到。

如何用Java反射提高開發(fā)效率的框架

然后再繼續(xù)對(duì)RowsetBean繼續(xù)以上步驟。還有一點(diǎn),就是RowsetBean被@ProdCampaignMapRules注解注釋,所以要獲取到@ProdCampaignMapRules注解,賦值給rowset的ClassNode節(jié)點(diǎn)的rule。

反射解析Response生成結(jié)構(gòu)數(shù),我是使用隊(duì)列加廣度優(yōu)先遍歷方法。代碼如下圖所示。

如何用Java反射提高開發(fā)效率的框架

如何用Java反射提高開發(fā)效率的框架

包掃描如何實(shí)現(xiàn)我就不說了。


根據(jù)OfferBean的Class結(jié)構(gòu)樹映射生成ProdCampaign


這一步我只介紹實(shí)現(xiàn)思路,每一步的具體實(shí)現(xiàn),整體的實(shí)現(xiàn)就不貼代碼了。


1.首先使用jackson解析調(diào)用第三方API返回的json字符串,得到Response對(duì)象。


2.根據(jù)Response的Class從緩存中獲取其類結(jié)構(gòu)樹。使用深度優(yōu)先搜索,取得被@ProdCampaignMapRules注釋的ClassNode。這個(gè)很好判斷,因?yàn)樵谇懊鎸㈩惿山Y(jié)構(gòu)樹的步驟,已經(jīng)取得@ProdCampaignMapRules注解并存放到了ClassNode的rule。


如何用Java反射提高開發(fā)效率的框架


3.獲取到被@ProdCampaignMapRules注釋的ClassNode后,取得該ClassNode所屬的FieldNode。


4.取得該FieldNode后,獲取Field,反射取得值,這個(gè)值就是要找的目標(biāo),即存放廣告Offer的集合。


如何用Java反射提高開發(fā)效率的框架


5.拿到存放廣告Offer的集合后,遍歷這個(gè)集合,將里面的每個(gè)元素,映射成平臺(tái)統(tǒng)一的存放廣告信息的ProdCampaign。最后就能獲取到ProdCampaign集合。


6.每個(gè)元素映射成ProdCampaign對(duì)象的過程,才是重點(diǎn),還是很復(fù)雜的。因?yàn)樾枰С侄鄬佑成洌褪侵С窒袷褂胢ybatis拼寫sql一樣支持“.”操作,如“offer.geo.country”,就是要取得offer對(duì)象的geo字段的值,再獲取geo的country字段的值。有了類結(jié)構(gòu)樹,多級(jí)映射并不難,只需要一個(gè)while循環(huán)即可。


如何用Java反射提高開發(fā)效率的框架  


7.對(duì)于tracklinkMap,是一個(gè)注解數(shù)組,類型是@TracklinkMap,用于聲明url需要哪些參數(shù),怎么拼接。


如何用Java反射提高開發(fā)效率的框架

“如何用Java反射提高開發(fā)效率的框架”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!


文章題目:如何用Java反射提高開發(fā)效率的框架
文章路徑:http://weahome.cn/article/psghch.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部