?
轉(zhuǎn)自: http://klcwt.iteye.com/blog/749652
?
我們?cè)诰帉?xiě)自定義標(biāo)簽的時(shí)候設(shè)置屬性如下
- public ? class ?InputTag? extends ?TagSupport?{??
- ??
- ???? private ? static ? final ? long ?serialVersionUID?=?1L;??
- ??
- ???? private ?String?onclick;??
- ??
- ???? private ?String?style;??
- ??
- ???? private ?String?styleClass;??
- ??
- ???? private ?String?value;??
- ??
- ???? private ?String?id;??
?
在頁(yè)面上如果同時(shí)使用兩個(gè)標(biāo)簽:
- < h3:input ? type = "button" ? onclick = "myFun()" ? name = "name" ? id = "id" ??
- ???????? style = "style" ? styleClass = "styleClass" ? value = "中國(guó)人" ? url = "url" ??
- ???????? pid = "pid" ? isValidated = "true" > ??
- ????中國(guó)人??
- ???? </ h3:input > ??
- ??????
- ???? < h3:input ? type = "button" ? onclick = "myFun()" ? name = "name" ? id = "id" ??
- ???????? style = "style" ? styleClass = "styleClass" ? value = "美國(guó)人" ? url = "url" ??
- ???????? pid = "pid" ? isValidated = "true" > ??
- ???? </ h3:input > ??
?
從后臺(tái)發(fā)現(xiàn)打印的InpuTag都是 同一個(gè)對(duì)象!
?
發(fā)現(xiàn)這個(gè)后,我十分擔(dān)心線程安全問(wèn)題!比如這些getType();setType(); !
?
于是就看了下jsp生成的Servlet源代碼
- out.write( "\t<body>\r\n" );??
- ??out.write( "\t\t" );??
- ??? //調(diào)用InputTag ??
- ?? if ?(_jspx_meth_h3_005finput_005f0(_jspx_page_context))??
- ???? return ;??
- ??out.write( "\r\n" );??
- ??out.write( "\t\t\r\n" );??
- ??out.write( "\t\t" );??
- ?? //調(diào)用InputTag ??
- ?? if ?(_jspx_meth_h3_005finput_005f1(_jspx_page_context))??
- ???? return ;??
- ??out.write( "\r\n" );??
- ??out.write( "\t</body>\r\n" );??
?
再接著看_jspx_meth_h3_005finput_005f0方法
- ?? private ? boolean ?_jspx_meth_h3_005finput_005f0(PageContext?_jspx_page_context)??
- ?????????? throws ?Throwable?{??
- ????PageContext?pageContext?=?_jspx_page_context;??
- ????JspWriter?out?=?_jspx_page_context.getOut();??
- ???? //??h3:input ??
- ???<span?style= "color:?#ff0000;" >?tag.InputTag?<span?style= "color:?#0000ff;" >_jspx_th_h3_005finput_005f0</span>?=?(tag.InputTag)?_005fjspx_005ftagPool_005fh3_005finput_0026_005fvalue_005furl_005ftype_005fstyleClass_005fstyle_005fpid_005fonclick_005fname_005fisValidated_005fid.get(tag.InputTag. class );</span>??
- ????_jspx_th_h3_005finput_005f0.setPageContext(_jspx_page_context);??
- ????_jspx_th_h3_005finput_005f0.setParent( null );??
- ???? //?/button2.jsp(12,2)?name?=?type?type?=?null?reqTime?=?true?required?=?false?fragment?=?false?deferredValue?=?false?expectedTypeName?=?null?deferredMethod?=?false?methodSignature?=?null ??
- ????_jspx_th_h3_005finput_005f0.setType( "button" );??
- ???? //?/button2.jsp(12,2)?name?=?onclick?type?=?java.lang.String?reqTime?=?false?required?=?true?fragment?=?false?deferredValue?=?false?expectedTypeName?=?null?deferredMethod?=?false?methodSignature?=?null????_jspx_th_h3_005finput_005f0.setPid("pid"); ??
- ???? //?/button2.jsp(12,2)?name?=?isValidated?type?=?null?reqTime?=?true?required?=?false?fragment?=?false?deferredValue?=?false?expectedTypeName?=?null?deferredMethod?=?false?methodSignature?=?null ??
- ????_jspx_th_h3_005finput_005f0.setIsValidated( "true" );??
- ???? int ?_jspx_eval_h3_005finput_005f0?=?_jspx_th_h3_005finput_005f0.doStartTag();??
- ???? if ?(_jspx_eval_h3_005finput_005f0?!=?javax.servlet.jsp.tagext.Tag.SKIP_BODY)?{??
- ?????? do ?{??
- ????????out.write( "\r\n" );??
- ????????out.write( "\t\t中國(guó)人\r\n" );??
- ????????out.write( "\t\t" );??
- ???????? int ?evalDoAfterBody?=?_jspx_th_h3_005finput_005f0.doAfterBody();??
- ???????? if ?(evalDoAfterBody?!=?javax.servlet.jsp.tagext.BodyTag.EVAL_BODY_AGAIN)??
- ?????????? break ;??
- ??????}? while ?( true );??
- ????}??
- ???? if ?(_jspx_th_h3_005finput_005f0.doEndTag()?==?javax.servlet.jsp.tagext.Tag.SKIP_PAGE)?{??
- ??????<span?style= "color:?#ff0000;" >_005fjspx_005ftagPool_005fh3_005finput_0026_005fvalue_005furl_005ftype_005fstyleClass_005fstyle_005fpid_005fonclick_005fname_005fisValidated_005fid.reuse(_jspx_th_h3_005finput_005f0);</span>??
- ?????? return ? true ;??
- ????}??
- <span?style= "color:?#ff0000;" >????_005fjspx_005ftagPool_005fh3_005finput_0026_005fvalue_005furl_005ftype_005fstyleClass_005fstyle_005fpid_005fonclick_005fname_005fisValidated_005fid.reuse(_jspx_th_h3_005finput_005f0);</span>??
- ???? return ? false ;??
- ??}??
最關(guān)鍵就是這句了,看他如何獲得自定義標(biāo)簽對(duì)象: tag.InputTag _jspx_th_h3_005finput_005f0 = (tag.InputTag) _005fjspx_005ftagPool_005fh3_005finput_0026_005fvalue_005furl_005ftype_005fstyleClass_005fstyle_005fpid_005fonclick_005fname_005fisValidated_005fid.get(tag.InputTag.class);
解釋下:
?_jspx_th_h3_005finput_005f0 是InputTag 的實(shí)例 也就是<h3:input.
而
005fjspx_005ftagPool_005fh3_005finput_0026_005fvalue_005furl_005ftype_005fstyleClass_005fstyle_005fpid_005fonclick_005fname_005fisValidated_005
是TagHandlerPool的實(shí)例
?
自定義標(biāo)簽是通過(guò)這個(gè)TagHandlerPool.get 來(lái)獲取的!
舉一反三,有借就有還TagHandlerPool.reuse用來(lái)回收這個(gè)對(duì)象!
?
?
TagHandlerPool.get?
TagHandlerPool.reuse
方法如下:
?
- /** ?
- ??*?Gets?the?next?available?tag?handler?from?this?tag?handler?pool, ?
- ??*?instantiating?one?if?this?tag?handler?pool?is?empty. ?
- ??* ?
- ??*?@param?handlerClass?Tag?handler?class ?
- ??* ?
- ??*?@return?Reused?or?newly?instantiated?tag?handler ?
- ??* ?
- ??*?@throws?JspException?if?a?tag?handler?cannot?be?instantiated ?
- ??*/ ??
- ? public ?Tag?get(Class?handlerClass)? throws ?JspException?{??
- g?handler?=? null ;??
- ????? synchronized (? this ?)?{??
- ????????? if ?(current?>=? 0 )?{??
- ?????????????handler?=?handlers[current--];??
- ????????????? return ?handler;??
- ?????????}??
- ?????}??
- ??
- ????? //?Out?of?sync?block?-?there?is?no?need?for?other?threads?to ??
- ????? //?wait?for?us?to?construct?a?tag?for?this?thread. ??
- ????? try ?{??
- ?????????Tag?instance?=?(Tag)?handlerClass.newInstance();??
- ?????????AnnotationHelper.postConstruct(annotationProcessor,?instance);??
- ????????? return ?instance;??
- ?????}? catch ?(Exception?e)?{??
- ????????? throw ? new ?JspException(e.getMessage(),?e);??
- ?????}??
- ?}??
?
- /** ?
- ?*?Adds?the?given?tag?handler?to?this?tag?handler?pool,?unless?this?tag ?
- ?*?handler?pool?has?already?reached?its?capacity,?in?which?case?the?tag ?
- ?*?handler's?release()?method?is?called. ?
- ?* ?
- ?*?@param?handler?Tag?handler?to?add?to?this?tag?handler?pool ?
- ?*/ ??
- public ? void ?reuse(Tag?handler)?{??
- ???? synchronized (? this ?)?{??
- ???????? if ?(current?<?(handlers.length?-? 1 ))?{??
- ????????????handlers[++current]?=?handler;??
- ???????????? return ;??
- ????????}??
- ????}??
- ???? //?There?is?no?need?for?other?threads?to?wait?for?us?to?release ??
- ????handler.release();??
- ???? if ?(annotationProcessor?!=? null )?{??
- ???????? try ?{??
- ????????????AnnotationHelper.preDestroy(annotationProcessor,?handler);??
- ????????}? catch ?(Exception?e)?{??
- ????????????log.warn( "Error?processing?preDestroy?on?tag?instance?of?" ???
- ????????????????????+?handler.getClass().getName(),?e);??
- ????????}??
- ????}??
- }??
?
?
現(xiàn)在就明白了所有的tag對(duì)象都是有一個(gè)對(duì)象池來(lái)維護(hù)的,一是方便了重用,而是做到了線程同步。
?
?總結(jié):自定義標(biāo)簽是線程安全的,同時(shí)也是可重用的!
?
同時(shí)又有另一個(gè)疑問(wèn)
?synchronized( this ) {
??????????? if (current >= 0) {
??????????????? handler = handlers[current--];
??????????????? return handler;
??????????? }
??????? }
感覺(jué)這種方法可能只能在一個(gè)頁(yè)面上共享,另一個(gè)頁(yè)面上的tag估計(jì)是不能共享的!
?
后來(lái)看了下生成的servelt代碼
如下:
- public ? void ?_jspInit()?{??
- ????_tagpool?=?org.apache.jasper.runtime.TagHandlerPool.getTagHandlerPool(getServletConfig());??
- ????_el_expressionfactory?=?_jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();??
- ????_jsp_annotationprocessor?=?(org.apache.AnnotationProcessor)?getServletConfig().getServletContext().getAttribute(org.apache.AnnotationProcessor. class .getName());??
- ??}??
?可以看到_tagpool 是根據(jù)ServletConifg來(lái)生成的
TagHandlerPool.getTagHandlerPool代碼如下
- public ? static ?TagHandlerPool?getTagHandlerPool(?ServletConfig?config)?{??
- ???????TagHandlerPool?result= null ;??
- ??
- ???????String?tpClassName=getOption(?config,?OPTION_TAGPOOL,? null );??
- ??????? if (?tpClassName?!=? null ?)?{??
- ??????????? try ?{??
- ???????????????Class?c=Class.forName(?tpClassName?);??
- ???????????????result=(TagHandlerPool)c.newInstance();??
- ???????????}? catch ?(Exception?e)?{??
- ???????????????e.printStackTrace();??
- ???????????????result= null ;??
- ???????????}??
- ???????}??
- ??????? if (?result== null ?)?result= new ?TagHandlerPool();??
- ???????result.init(config);??
- ??
- ??????? return ?result;??
- ???}??
?
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
