JavaBean組件學(xué)習(xí)筆記

??本文涉及重要概念:反射、內(nèi)省、BeanUtils工具、JSP標(biāo)簽。
??這幾個(gè)概念看起來相關(guān)性不大,其實(shí)都是用于控制JavaBean的方法。其中,前面三種都是在java(例如在Servlet)文件中訪問和修改JavaBean的方法。而JSP標(biāo)簽則是在jsp文本中訪問JavaBean的方法。
??在這之前,如果我們想要操作屬性,一般情況下我們先是先將類實(shí)例化來得到一個(gè)對(duì)象。然后通過setter和getter方法對(duì)這個(gè)對(duì)象的屬性進(jìn)行操作,當(dāng)然,這是訪問屬性,如果直接用對(duì)象來調(diào)用方法也沒什么不妥。
??雖然JSP標(biāo)簽方法看起來繁雜(主要是指標(biāo)簽使用方面),但是它的原理確實(shí)最簡(jiǎn)單的,和上面類似,它對(duì)屬性的操作本質(zhì)上還是直接通過對(duì)象的getter和setter方法來進(jìn)行實(shí)現(xiàn)(具體的標(biāo)簽的內(nèi)容將在后面描述)。
??而其他三個(gè)都是采用不同方式來進(jìn)行屬性的訪問。按照我的理解,反射功能最為強(qiáng)大,它允許通過一個(gè)實(shí)例化對(duì)象找到類的完整信息并得到Class類。而Class類除了能操作屬性還能操作方法。內(nèi)省則是JDK中專門設(shè)計(jì)用于操作Java對(duì)象屬性的一套API。BeanUtils是Apache軟件基金會(huì)提供的一套能動(dòng)態(tài)訪問Java對(duì)象屬性的API,在這三者中最為簡(jiǎn)潔。這三個(gè)類都需要依賴于其他的類來進(jìn)行對(duì)象屬性的設(shè)置,并且不管是哪一種方法,原有的對(duì)象都從屬性的調(diào)用者變成了參數(shù)。而真正的方法的調(diào)用者是我們所依賴的這些新的對(duì)象。反射中所依賴的是Class類調(diào)用getDeclaredField(String<屬性名>)方法得到的Field類、內(nèi)省中所依賴的主要是PropertyDescriptor類,而BanUtils工具中所依賴的主要是BeanUtils類。但是BeanUtils類不需要實(shí)例化就可以調(diào)用方法,而反射和內(nèi)省的這些類都需要實(shí)例化。


反射:

??任何對(duì)象通過getclass()方法它就可以得到一個(gè)class類的實(shí)例,并且通過這個(gè)class類的方法就可以獲取類的完整信息。
??假如我有一個(gè)蘋果對(duì)象、一個(gè)貓對(duì)象和一個(gè)手機(jī)對(duì)象,它們各自使用getclass()都可以返回一個(gè)class對(duì)象。盡管這三個(gè)對(duì)象本身有不同的屬性和方法。但是它們返回的class對(duì)象卻有相同的方法和屬性(不過這些值不同)。通過對(duì)象調(diào)用getClass()獲得一個(gè)Class類的實(shí)例,需要先創(chuàng)建出一個(gè)對(duì)象(先要有一個(gè)蘋果/貓/手機(jī))。
??除了使用對(duì)象.getClass()方法來獲得class實(shí)例以外,還可以通過Class類的靜態(tài)方法forName(),用類的全路徑名獲取一個(gè)Class實(shí)例。這種方法不需要提前建立一個(gè)(蘋果/貓/狗)對(duì)象。

Class clazz = Class.forName("cn.itcast.chapter08.reflection.Person");

??這里是直接由于Class類來創(chuàng)建Class實(shí)例,并在參數(shù)中引入具體的類(例如這里的Person類)的路徑。
Class類調(diào)用forName(<Person類的路徑>)方法--->創(chuàng)建關(guān)于 Person類的clazz實(shí)例-----> clazz實(shí)例可以創(chuàng)建Person類的實(shí)例。

Person p= (Person)clazz.newInstance();

這段話看起來有一點(diǎn)繞。

??使用clazz創(chuàng)建對(duì)象時(shí),如果有多個(gè)構(gòu)造方法,那么情況更復(fù)雜,需要使用getConstructor()方法得到一個(gè)構(gòu)造方法對(duì)象(實(shí)際上是Constructor對(duì)象)的數(shù)組,然后由數(shù)組中對(duì)應(yīng)的某個(gè)Constructor對(duì)象(通過下標(biāo)選取)來創(chuàng)建對(duì)象。(在我看來,這里數(shù)組中的每個(gè)cons元素都可以理解為選定了特定構(gòu)造方法的clazz)。

Constructor cons[] = clazz.getConstructors();
Person p = (Person)cons[0].newInstance("李芳",30);

??和通過對(duì)象直接調(diào)用setter或者getter來修改屬性不同,現(xiàn)在用了反射。要修改對(duì)象的屬性,對(duì)象無需調(diào)用任何的方法,只需要老老實(shí)實(shí)作為參數(shù)進(jìn)行傳遞就行了。
具體的屬性會(huì)用一個(gè)Field類型的對(duì)象來表示,而具體的方法會(huì)用一個(gè)Method對(duì)象來表示。這些對(duì)象都是通過class類來生成。

Field ageField = clazz.geetDeclaredField("age");
ageField.setAccessible(true);
ageField.set(p,20);

反射獲取方法部分示例代碼如下所示:

Method md = clazz.getMethod("sayHello",String.class,int.class);
String result =(String)md.invoke(clazz.newInstance())

??也即是說,不管是通過反射調(diào)用屬性還是方法,原本是通過該類的實(shí)例化對(duì)象來調(diào)用,而現(xiàn)在全部可以通過class類的實(shí)例對(duì)象(例如clazz)來完成。并且屬性、方法全部都變成了對(duì)象(age屬性生成一個(gè)Field對(duì)象,sayHello方法生成一個(gè)Method對(duì)象),并且這些對(duì)象全部都可以通過clazz一步得到,而原來的實(shí)例對(duì)象從方法和屬性的執(zhí)行者,現(xiàn)在變成了參與者。

內(nèi)省

??內(nèi)省是專門用于操作java對(duì)象的屬性,它比反射技術(shù)更加便捷。
??反射可以實(shí)現(xiàn)操作方法、屬性的功能,而這里內(nèi)省專門操作java對(duì)象的屬性,從功能上看略差一籌。但是在屬性的操作方面,它有它的便捷之處。在內(nèi)省中也運(yùn)用到了反射中的class類。

Person p  = new Person();
PropertyDescriptor pd = new PropertyDescriptor("name",p.getclass());
Method methodName = pd.getWriterMethod();
methodName.invoke(p,"小明");

??同樣是訪問屬性,這里的思路跟用反射訪問屬性的思路就不同了。上面說過反射是利用class類的一個(gè)實(shí)例clazz來調(diào)用getDeclaredField(String name)方法來得到一個(gè)關(guān)于某個(gè)屬性Field對(duì)象,這個(gè)Filed對(duì)象就可以直接更改對(duì)應(yīng)的屬性值。
??而這里p.getClass()同樣生成一個(gè)class類的實(shí)例,但是呢不直接利用這個(gè)實(shí)例,而是繼續(xù)把這個(gè)class實(shí)例和我們的屬性值作為參數(shù)創(chuàng)建出一個(gè)PropertyDescriptor對(duì)象。
??這兩者的區(qū)別,如果是第一種方法,那么當(dāng)我要訪問多個(gè)屬性,那我還是只需要一個(gè)clazz對(duì)象。但如果是通過內(nèi)省的方法,每次訪問一個(gè)屬性,都需要新創(chuàng)建一個(gè)Class類實(shí)例對(duì)象,并作為參數(shù)用于生成新的PropertyDescriptor對(duì)象。
??這還沒完,如果想要對(duì)屬性進(jìn)行更改。還需要調(diào)用getWriteMethod()得到一個(gè)method對(duì)象,這個(gè)method對(duì)象才能夠?qū)傩赃M(jìn)行更改,如果只是進(jìn)行讀取,那么就調(diào)用getReadMethod()。說句實(shí)在話,我看不出來哪里便捷了。


Beanutils工具

??beanutils提供了比反射和內(nèi)省更為簡(jiǎn)單的操作,Beanutils工具包還需要一個(gè)logging包來配合使用。logging包中包裝了各種日志API的實(shí)現(xiàn)。BeanUtils工具中最核心的是org.apache.commons.beanutils包下的BeanUtils類。BeanUtils直接調(diào)用setProperty方法就可以搞定屬性的修改。

Person p = new Person();
BeanUtils.setProperty(p,"name","Jack");
BeanUtils.getProperty(p,"name");

并且能夠通過populate方法同時(shí)修改多個(gè)屬性。

  Map<String,Object>map = new HashMap<String,Object>();
   map.put("name","張三");
    map.put("age",10)
   BeanUtils.populate(p,map)

但是我們同樣也要意識(shí)到,這里只是訪問屬性方便。方法就不見得能訪問了。


JSP標(biāo)簽訪問JavaBean

??jsp文件訪問JavaBean和更改其屬性可以通過標(biāo)簽來進(jìn)行實(shí)現(xiàn)。但是其對(duì)屬性的操作本質(zhì)上還是利用了這個(gè)對(duì)象直接調(diào)用getter和setter的方法來進(jìn)行實(shí)現(xiàn)。因此,接下來的內(nèi)容是對(duì)標(biāo)簽用法的一些介紹。
??<jsp:useBean>表示可以在某個(gè)指定的域的范圍中查找一個(gè)指定名稱的JavaBean對(duì)象。如果已經(jīng)存在對(duì)象則返回該對(duì)象,否則實(shí)例化一個(gè)JavaBean對(duì)象并儲(chǔ)存在指定的域中。

??<jsp:setProperty>標(biāo)簽有name、property、param和value四個(gè)屬性。其中name和property好理解,表明要修改的是名為name的JavaBean實(shí)例對(duì)象的property屬性。這時(shí)候,如果我們?cè)L問這個(gè).jsp文件,URL鏈接后面的參數(shù)如果和property的名字相對(duì)應(yīng)的,會(huì)自動(dòng)賦值到這個(gè)屬性。如果參數(shù)名字和property名字不同但是仍然想賦值,那么可以用param進(jìn)行映射。如果就算參數(shù)相同也不希望進(jìn)行賦值的,可以使用value屬性為其賦值,這樣就不受URL請(qǐng)求中的參數(shù)的影響。


JSP開發(fā)模型的Model1與Model2的區(qū)別的理解

JSP Model1:JSP+JavaBean
JSP Model2:Servlet + JSP + JavaBean
??可以看到,兩種模型都使用了JavaBean技術(shù)。不同之處在于JspModel1模型沒有引入專門的Servlet。因此控制邏輯都在.jsp中進(jìn)行實(shí)現(xiàn),不可避免地.jsp頁面中含有大量的代碼片段。
??而JspModel2則是將部分代碼片段抽離出來,封裝到Servlet中,只留下一些與顯示相關(guān)的代碼段。實(shí)現(xiàn)了 頁面顯示、流程控制和業(yè)務(wù)邏輯 的分離。
??說的通俗些,.jsp曾經(jīng)是一個(gè)無所不能的存在,但是我們不忍心看它忙的焦頭爛額,所以我們用JavaBean來幫它控制數(shù)據(jù)庫。再使用Servlet幫他處理一些業(yè)務(wù)邏輯,這樣也有利于代碼的維護(hù)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,775評(píng)論 18 399
  • Spring Web MVC Spring Web MVC 是包含在 Spring 框架中的 Web 框架,建立于...
    Hsinwong閱讀 22,960評(píng)論 1 92
  • 過去的520,一眾單身狗直呼被虐得體無完膚?;艚ㄈA、林心如男神女神也在這天公布了相戀的消息。真好,哪怕中間錯(cuò)過了太...
    宋小溫閱讀 582評(píng)論 4 8
  • 2018-1-25今天晚上看了四個(gè)小視頻,第一個(gè)講的是六十歲320磅的女性,再不減肥就有生命危險(xiǎn),為了活下去,堅(jiān)持...
    洛陽一清閱讀 396評(píng)論 0 1
  • 2016/12/17/星期六/丙申年冬月十九 天氣突然驟降 真的很冷很冷 剛看完《夏有喬木雅望天堂》看的不是很懂 ...
    木槿花開阿閱讀 317評(píng)論 0 0

友情鏈接更多精彩內(nèi)容