標籤:
一、ant:http://ant.apache.org/bindownload.cgi
二、log4j:http://logging.apache.org/log4j/2.x/download.html
三、內省
1.什麼是內省。
本質上是反射,具體技術由sun替公司提供,整合到了jdk中,可以根據欄位名稱(String)和位元組碼對象得到該欄位的一個描述:PropertyDescriptor,並由此得到該欄位的get、set方法(Method)。
將要使用的JavaBean
1 package com.kdyzm.domain; 2 3 import java.util.Date; 4 5 public class Person { 6 private String name; 7 private Integer age; 8 private Date date; 9 10 public Person(String name, Integer age, Date date) {11 this.name = name;12 this.age = age;13 this.date = date;14 }15 public String getName() {16 return name;17 }18 public void setName(String name) {19 this.name = name;20 }21 public Integer getAge() {22 return age;23 }24 public void setAge(Integer age) {25 this.age = age;26 }27 public Date getDate() {28 return date;29 }30 public void setDate(Date date) {31 this.date = date;32 }33 public Person() {34 }35 @Override36 public String toString() {37 return "Person [name=" + name + ", age=" + age + ", date=" + date + "]";38 }39 }
2.核心類:
(1)PropertyDescriptor類。
[1]繼承關係
java.lang.Object
|--java.beans.FeatureDescriptor
|--java.beans.PropertyDescriptor
[2]構造方法
構造方法摘要 |
PropertyDescriptor(String propertyName, Class<?> beanClass) 通過調用 getFoo 和 setFoo 存取方法,為符合標準 Java 約定的屬性構造一個 PropertyDescriptor。 |
|
PropertyDescriptor(String propertyName, Class<?> beanClass, String readMethodName, String writeMethodName) 此構造方法帶有一個簡單屬性的名稱和用於讀寫屬性的方法名稱。 |
|
PropertyDescriptor(String propertyName, Method readMethod, Method writeMethod) 此構造方法帶有某一簡單屬性的名稱,以及用來讀取和寫入屬性的 Method 對象。 |
|
[3]核心方法
Class<?>
|
getPropertyType() 獲得屬性的 Class 對象。 |
Method |
getReadMethod() 獲得應該用於讀取屬性值的方法。 |
Method |
getWriteMethod() 獲得應該用於寫入屬性值的方法。 |
void |
setReadMethod(Method readMethod) 設定應該用於讀取屬性值的方法。 |
void |
setWriteMethod(Method writeMethod) 設定應該用於寫入屬性值的方法。 |
[4]使用樣本。
獲的setName方法並給Person對象賦值。
public void test1() throws Exception { Person p=new Person(); /* //這裡是通過普通的反射方法來實現的。 Method method=p.getClass().getMethod("setName", String.class); method.invoke(p, "張三"); System.out.println(p); */ //下面通過使用內省的方式來實現該目的。 PropertyDescriptor pd=new PropertyDescriptor("name", p.getClass(),"getName","setName"); Method getName=pd.getReadMethod(); String name=(String) getName.invoke(p); System.out.println(name); Method setName=pd.getWriteMethod(); setName.invoke(p, "小強"); getName=pd.getReadMethod(); System.out.println(getName.invoke(p)); /* * 輸出結果: * null * 小強 */ }
不能進行類型的自動轉換。
public void test2() throws Exception { Person p=new Person(); PropertyDescriptor pd=new PropertyDescriptor("age", p.getClass()); Method setAge=pd.getWriteMethod(); setAge.invoke(p, "12");//這裡只能傳遞整數類型的參數,所以一定會報錯! System.out.println(p); }
(2)BeanInfo介面:專門分析一個JavaBean有多少屬性,有哪些屬性
[1]擷取該介面執行個體的方法
使用Introspector(內省)類( java.lang.Object )的靜態方法:getBeanInfo(Class<?> beanClass)
|--java.bean.Introspector
static BeanInfo |
getBeanInfo(Class<?> beanClass) 在 Java Bean 上進行內省,瞭解其所有屬性、公開的方法和事件。 |
[2]核心方法:getPropertygetDescriptors方法。
PropertyDescriptor[] |
getPropertyDescriptors() 獲得 beans PropertyDescriptor。 |
[3]使用方法。
/* * 測試非常不好的類:BeanInfo類,該類並不會將一個Bean對象的所有屬性都能解析成功,反而是只要是 * get或者set方法都會 * 解析出來。 * 所以即使是getClass方法該類也會將其作為class屬性解析出來。 * 如果不成對,也會解析出來。 */ @Test public void test3() throws Exception { BeanInfo beaninfo=Introspector.getBeanInfo(Person.class); PropertyDescriptor pd[]=beaninfo.getPropertyDescriptors(); for(int i=0;i<pd.length;i++) { String name=pd[i].getName(); System.out.println(name); } }
3.解決類型不符的方法:遍曆判斷
(1)情境:Person類有age成員變數,為int類型,如果想要傳遞一個字串給它,一般情況下會報錯:不匹配的參數類型。怎樣解決這個問題呢?對set方法能接受的參數類型進行判斷,如果是整型參數才傳遞。
(2)手動遍曆解決。
/* * 怎樣實現將字串傳遞到setAge方法中 * 通過使用便利的方式依次對set方法進行遍曆 * 這裡的JavaBean必須是Integer類型的,否則不識別。 * 這麼麻煩的工作apache已經將其簡化開發出了第三方jar包:BeanUtils.jar */ @Test public void test4() throws Exception, IllegalArgumentException, IllegalAccessException, InvocationTargetException { String name="小強"; String age="30"; Person p=new Person(); Method methods[]=p.getClass().getDeclaredMethods(); for(Method method:methods) { String methodname=method.getName(); //如果是set方法才行進下一步,get方法直接跳過 if(methodname.startsWith("set")) { Class<?> clazz[]=method.getParameterTypes(); System.out.println(clazz[0]); if(clazz[0].equals(String.class)) { method.invoke(p,name); } else if(clazz[0].equals(Integer.class)) { method.invoke(p, Integer.parseInt(age)); } } else continue; } System.out.println(p); }
4.使用第三方jar包:BeanUtils.jar解決 3 中的問題以及使用第三方jar包的好處。
BeanUtils.jar:http://commons.apache.org/proper/commons-beanutils/download_beanutils.cgi
依賴包:commons-logging.jar包
(1)BeanUtils.jar是幹什麼用的?
是一個處理JavaBean的工具包,內部也是使用內省,但是對內省進行了加強。
(2)使用該工具包的好處是什嗎?
JavaBean中的get方法和set方法不用再成對出現。
能夠自動進行基礎資料型別 (Elementary Data Type)的轉換(不是基礎資料型別 (Elementary Data Type)不能自動進行轉換)。
(3)示範使用BeanUtils設定值。
//示範使用BeanUtils設定值 @Test public void setValueTest() throws Exception, Exception { Person p=new Person(); BeanUtils.setProperty(p,"name", "小強"); BeanUtils.setProperty(p, "age", "45"); BeanUtils.setProperty(p, "date", new Date()); System.out.println(p); }
(4)示範使用BeanUtils擷取值。
//示範使用BeanUtils擷取值。 @Test public void getValueTest() throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { Person p=new Person("小強",24,new Date()); System.out.println(BeanUtils.getProperty(p, "name")); System.out.println(BeanUtils.getProperty(p, "age")); System.out.println(BeanUtils.getProperty(p, "date")); }
(5)使用BeanUtils一次性將擷取到的值封裝到javaBean中。
//使用Benutils一次性填入所有值的方法 @Test public void setValueAll() throws Exception, InvocationTargetException { Person p=new Person(); Map<String,Object>map=new HashMap<String,Object>(); map.put("name", "小強"); map.put("age", "24"); map.put("date", new Date()); BeanUtils.populate(p, map); //這句是關鍵 System.out.println(p); //這種方式在分析表單提交的資料並封裝成JavaBean的時候使用的非常廣泛,因為可以大大節省代碼量,注意要使用request對象的getParameterMap()方法。 }
【Java EE 學習第23天】【log4j的使用】【ant的使用】【內省】