※getPropertyDescriptors
利用setter/getter其中之一來達到抓取的目的,但有以下幾點要注意就算沒有給屬性(所以屬性的修飾子是什麼無所謂),
.setter:public void set開頭就抓的到
.getter:public而且回傳值不是void,且沒有參數,就算回傳的是個null也可抓的到
set/get開頭後面一定要有,不能剛好是set/get
package inheritate; public class Son extends Dad { private int son; private int son2; private String son3; // setter/getter... } ------------------------------ package inheritate; public class Dad extends Father { private String dad; // setter/getter... } ------------------------------ package inheritate; public abstract class Father implements GrandFather { private String father; // setter/getter... } ------------------------------ package inheritate; public interface GrandFather { String grandFather = "g"; default String getGrandFather() { return grandFather; } }
※雖然最後是介面,也有屬性,但內省是不會理他的,因為介面本來就沒有什麼setter/getter
※測試
Son son = new Son(); son.setSon(1); son.setDad("d1"); son.setFather("d2"); /* Son s; try { Class<?> clazz = Class.forName("inheritate.Son"); try { s = (Son) clazz.newInstance(); s.setSon(2); s.setDad("s1"); s.setFather("s2"); } catch (InstantiationException | IllegalAccessException e) { e.printStackTrace(); } } catch (ClassNotFoundException e1) { e1.printStackTrace(); } */ BeanInfo bi = null; try { bi = Introspector.getBeanInfo(son.getClass()); } catch (IntrospectionException e) { e.printStackTrace(); } PropertyDescriptor[] pds = bi.getPropertyDescriptors(); System.out.println("pds長度=" + pds.length + System.getProperty("line.separator")); for (PropertyDescriptor p : pds) { System.out.println("name=" + p.getName()); System.out.println("propertyType=" + p.getPropertyType()); Method rm = p.getReadMethod(); try { System.out.println("invoke=" + rm.invoke(son)); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { e.printStackTrace(); } System.out.println(); }
※結果:
pds長度=6
name=class
propertyType=class java.lang.Class
invoke=class inheritate.Son
name=dad
propertyType=class java.lang.String
invoke=d1
name=father
propertyType=class java.lang.String
invoke=d2
name=son1
propertyType=int
invoke=1
name=son2
propertyType=int
invoke=0
name=son3
propertyType=class java.lang.String
invoke=null
※Son有三個屬性,而Dad、Father各有一個屬性,所以會有5個,但看結果會多一個class的屬性
※getBeanInfo有四個建構子,其中的兩個參數,有給class和int的
.class表示在哪個class就停止搜尋下去的意思,停止的class不會搜尋
所以以上面的結果,如果不想要Class,就可以在getBeanInfo增加第二個參數Object.class就不會出現class屬性了,又如果我給Father.class,那結果就是4個,因為Son繼承Dad,Father不會搜尋
.int有三種,都是static的
USE_ALL_BEANINFO:如果第二個參給這個值,它會連到三個參數的建構子,所以第二個肯定是null,這時等同一個參數的建構子
IGNORE_IMMEDIATE_BEANINFO:待補充
IGNORE_ALL_BEANINFO:待補充
※實體可不同,如下
BeanInfo bi = null; try { bi = Introspector.getBeanInfo(Son.class, Dad.class); } catch (IntrospectionException e) { e.printStackTrace(); } PropertyDescriptor[] pds = bi.getPropertyDescriptors(); System.out.println("pds長度=" + pds.length + System.getProperty("line.separator")); Son son = new Son(); for (PropertyDescriptor p : pds) { Method wm = p.getWriteMethod(); Method rm = p.getReadMethod(); if (p.getName().equals("son3")) { try { wm.invoke(son, "xxx"); System.out.println("invoke=" + rm.invoke(son)); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { e.printStackTrace(); } System.out.println(); } else if (p.getName().equals("son1")) { try { wm.invoke(son, 2); System.out.println("invoke=" + rm.invoke(son)); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { e.printStackTrace(); } } }
※Son的實體沒有放在getBeanInfo裡面,但還是OK的
※此例塞son3和son1屬性,其他就不塞,所以不塞的該是null就是null;該是0就是0
※getWriteMethod對應setter方法;getReadMethod對應getter方法,如果其中一個沒有,那對應的方法就會報錯
※由於屬性和setter/getter的名稱是可以不匹配的,所以java bean如下的設定也是可以的
package inheritate; public class Son extends Dad { private int s; private int s2; private String s3; public int getSon() { return s; } public void setSon(int son1) { this.s = son1; } public int getSon2() { return s2; } public void setSon2(int son2) { this.s2 = son2; } public String getSon3() { return s3; } public void setSon3(String son3) { this.s3 = son3; } }
※
※PropertyDescriptor
少了一個s,這時屬性修飾子依然無所謂,但setter/getter都一定要有※測試
try { PropertyDescriptor pd = new PropertyDescriptor("son4", Son.class); Method m1 = pd.getWriteMethod(); Method m2 = pd.getReadMethod(); Son son = new Son(); try { m1.invoke(son, "xxx"); // 呼叫setSon4 System.out.println(m2.invoke(son)); // 呼叫getSon4 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { e.printStackTrace(); } } catch (IntrospectionException e) { e.printStackTrace(); }
※直接利用PropertyDescriptor的建構子即可達到目的,第二個參數放Class,第一個參數放第二個參數裡的屬性名稱
※屬性和setter/getter的名稱是仍然是不匹配的,所以java bean如下的設定也是可以的
package inheritate; public class Son extends Dad { private String son1; public String getSon4() { return "ooo"; } public void setSon4(String son4) { this.son1 = son4; } }
※
※getMethodDescriptors
BeanInfo bi = null; try { bi = Introspector.getBeanInfo(Son.class, Dad.class); } catch (IntrospectionException e) { e.printStackTrace(); } MethodDescriptor[] mds = bi.getMethodDescriptors(); System.out.println("mds長度=" + mds.length + System.getProperty("line.separator")); for (MethodDescriptor m : mds) { System.out.println("name=" + m.getName()); System.out.println("value=" + m.getValue(m.getName())); if ("setSon3".equals(m.getName())) { m.setValue(m.getName(), "xxx"); System.out.println("value=" + m.getValue(m.getName())); } Enumeration<String> attrs = m.attributeNames(); while(attrs.hasMoreElements()){ System.out.println(attrs.nextElement()); } System.out.println(); }
※
※公用
apache提供了一個方便的工具,但要下載※
<dependency> <groupId>commons-beanutils</groupId> <artifactId>commons-beanutils</artifactId> <version>1.9.3</version> </dependency>
※
※測試
public static void main(String[] args) throws Exception { Son son = new Son(); BeanUtils.setProperty(son, "son", "1"); BeanUtils.setProperty(son, "son2", "2"); BeanUtils.setProperty(son, "son3", "xxx"); System.out.println(BeanUtils.getProperty(son, "son")); System.out.println(BeanUtils.getProperty(son, "son2")); System.out.println(BeanUtils.getProperty(son, "son3")); Son s = new Son(); PropertyUtils.setProperty(s, "son", 3); PropertyUtils.setProperty(s, "son2", 4); PropertyUtils.setProperty(s, "son3", "ooo"); System.out.println(PropertyUtils.getProperty(s, "son")); System.out.println(PropertyUtils.getProperty(s, "son2")); System.out.println(PropertyUtils.getProperty(s, "son3")); }
※BeanUtils在set時,可以全部都用字串塞值,但PropertyUtils一定要塞對的型態,否則會報錯
※還是要依照java bean才有辦法塞/取值
沒有留言:
張貼留言