基于注解搭建WebService框架的反射使用

此次搭建的WebApi平臺思路如下踊淳;

1.對攔截到的Action請求統(tǒng)一構(gòu)建context對象,用于組裝請求所攜帶的參數(shù)。

2.構(gòu)建統(tǒng)一的響應(yīng)對象reponse

3.調(diào)用checkSecurity檢查模塊檢查請求的安全性和可用性诚纸,如有錯誤,則退出處理并寫入response錯誤信息

4.對通過check的context對象進行反射調(diào)用陈惰,并根據(jù)相應(yīng)結(jié)果組裝response對象

5.response對象通過Marshaller模塊返回指定的響應(yīng)報文

注:其中的3和5過程都需要提供可繼承的接口方便用戶自定義策略

在編碼過程中遇到的較大難題主要是反射調(diào)用這一塊畦徘,也是我覺得有價值的地方,特記錄如下抬闯。

先復(fù)習(xí)一下spring.beans包的主要內(nèi)容


spring beans

總結(jié)如下:

1.Loading XML bean definitions

2.實例化BeanFactoryPostProcessor井辆,調(diào)用工廠方法

3.實例化BeanPostProcessor構(gòu)造器

4.實例化InstantiationAwareBeanPostProcessorAdapter

5.調(diào)用postProcessBeforeInstantiation方法,構(gòu)造目標bean實例溶握。再調(diào)用postProcessPropertyValues方法杯缺,為目標bean注入屬性

6.BeanPostProcessor接口方法postProcessBeforeInitialization對屬性進行更改!

7.【init-method】調(diào)用的init-method屬性指定的初始化方法

8.BeanPostProcessor接口方法postProcessAfterInitialization對屬性進行更改睡榆!

9.InstantiationAwareBeanPostProcessor調(diào)用postProcessAfterInitialization方法

10.容器初始化成功


其中可以看出萍肆,beanPostProcessor接口對spring接管的每個實體類都會調(diào)用postProcessBeforeInitialization,postProcessAfterInitialization這兩個方法胀屿。

為了實現(xiàn)讓spring反射知道調(diào)用的是哪個方法塘揣,我需要在緩存中記住每個帶有

@BopServiceMethod(method = "sayHelloTest", args = {"webctx","name","data"}, message = "哼哈嘿")

注解的service方法,并讀取其中指定的method,args,message信息進行緩存宿崭。

為此亲铡,我們只要實現(xiàn)BeanPostProcessor接口,在postProcessAfterInitialization中判斷①該方法所在的類是否是service ②該類中的方法是否帶有@BopServoceMethod注解就行了

AnnotationUtils.findAnnotation(proClass, org.springframework.stereotype.Service.class);

使用findAnnotation方法判斷一個類上是否有@service注解葡兑。proClass表示目標類的class

Method[] methods = ReflectionUtils.getAllDeclaredMethods(proClass);

若是service類奴愉,則使用getAllDeclaredMethods方法獲得該類的所有方法組成數(shù)組

BopServiceMethod bopService = AnnotationUtils.findAnnotation(method, BopServiceMethod.class);

遍歷所有方法,獲得注解類铁孵,當注解類bopService不為空時,即說明該方法上標注了該注解房资。此時蜕劝,再用過method對象和bopService對象獲取需要的信息就易如反掌了。


在Spring中,凡是標注了@Transactional(事務(wù))注解的方法都會使用spring事務(wù)進行處理岖沛,spring框架使用過jdkDynamicProxy動態(tài)代理進行處理的暑始。或者是自己篇日志Aop動態(tài)代理的的方法婴削,在通過BeanPostProcessor接口時獲取的bean對象統(tǒng)統(tǒng)都是代理對象廊镜,這時直接使用bean.class作為參數(shù)拿到的Service類一定是Null

于是在此做如下處理:

Class proClass;

if (AopUtils.isJdkDynamicProxy(bean)) {

proClass = AopUtils.getTargetClass(bean);

} else {

proClass = bean.getClass();

}

該段代碼的含義是,通過AopUtils工具判斷是何種動態(tài)代理方式(這里我只判斷是否是jdk動態(tài)代理)唉俗,如果是嗤朴,則使用getTargetClass獲取其代理目標類的class。若不是虫溜,則直接獲得bean.class

除去使用這種方式以外雹姊,還可以通過以下這種方式獲得代理類的class

DirectFieldAccessor ads = new DirectFieldAccessor(Proxy.getInvocationHandler(bean));

AdvisedSupport advised = (AdvisedSupport) ads.getPropertyValue("advised");

clazz = advised.getTargetClass();

獲取invocationHandler對象,再構(gòu)建DirectFieldAccessor實例,通過屬性方法獲得advised的實例衡楞,再從advised對象中獲取目標類的class吱雏;


接下來講一講具體反射的使用思路

首先是緩存中拿到我們需要的各種屬性

類名、方法名和參數(shù)類型數(shù)組

Method mh = ReflectionUtils.findMethod(SpringContextUtil.getBean(className).getClass(), methodName, argsType);

使用ReflectionUtils.findMethod獲取反射的方法對象

然后瘾境,就是重點【參數(shù)轉(zhuǎn)換】

Object[] param = new Object[mh.getParameterCount()];

Class[] mhTypes = mh.getParameterTypes();

String[] argsName = (String[]) m.get("argsName");

① 首先歧杏,要通過mh.getParameterCount()取得參數(shù)的數(shù)量,并以此新建參數(shù)數(shù)組object[]

②通過mh.getParameterTypes()方法獲得所有的參數(shù)類型數(shù)組迷守,class<?>[]

③從緩存中取出我們之前緩存的參數(shù)名數(shù)組String[]

④提供參數(shù)轉(zhuǎn)換策略犬绒。遍歷對象進行替換!

由于我使用的context對象將所有參數(shù)都封裝成了json字符串盒犹,所以提供的轉(zhuǎn)換策略里需要JsonUtil工具類去轉(zhuǎn)換成各種需要的參數(shù)對象懂更。

最后,反射調(diào)用:

Object result = ReflectionUtils.invokeMethod(mh, SpringContextUtil.getBean(className), param);

完事急膀。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末沮协,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子卓嫂,更是在濱河造成了極大的恐慌慷暂,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件晨雳,死亡現(xiàn)場離奇詭異行瑞,居然都是意外死亡,警方通過查閱死者的電腦和手機餐禁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門血久,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人帮非,你說我怎么就攤上這事氧吐《锬ⅲ” “怎么了?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵筑舅,是天一觀的道長座慰。 經(jīng)常有香客問我,道長翠拣,這世上最難降的妖魔是什么版仔? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮误墓,結(jié)果婚禮上蛮粮,老公的妹妹穿的比我還像新娘。我一直安慰自己优烧,他們只是感情好蝉揍,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著畦娄,像睡著了一般又沾。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上熙卡,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天杖刷,我揣著相機與錄音,去河邊找鬼驳癌。 笑死滑燃,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的颓鲜。 我是一名探鬼主播表窘,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼甜滨!你這毒婦竟也來了乐严?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤衣摩,失蹤者是張志新(化名)和其女友劉穎昂验,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體艾扮,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡既琴,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了泡嘴。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片甫恩。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖酌予,靈堂內(nèi)的尸體忽然破棺而出填物,到底是詐尸還是另有隱情纹腌,我是刑警寧澤,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布滞磺,位于F島的核電站,受9級特大地震影響莱褒,放射性物質(zhì)發(fā)生泄漏击困。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一广凸、第九天 我趴在偏房一處隱蔽的房頂上張望阅茶。 院中可真熱鬧,春花似錦谅海、人聲如沸脸哀。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽撞蜂。三九已至,卻和暖如春侥袜,著一層夾襖步出監(jiān)牢的瞬間蝌诡,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工枫吧, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留浦旱,地道東北人。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓九杂,卻偏偏與公主長得像颁湖,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子例隆,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容