JavaBean及其內省操作

一、JavaBean簡介

JavaBean是使用Java語言開發的一個可重用的組件,在JSP的開發中可以使用JavaBean減少重複代碼,使整個JSP代碼的開發更簡潔。JSP搭配JavaBean來使用,有以下的優點:

1.可將HTML和Java代碼分離,這主要是爲了日後維護的方便。如果把所有的程序代碼(HTML和Java)寫到JSP頁面中,會使整個程序代碼又多又複雜,造成日後維護上的困難。

2.可利用JavaBean的優點。將日常用到的程序寫成JavaBean組件,當在JSP要使用時,只要調用JavaBean組件來執行用戶所要的功能,不用再重複寫相同的程序,這樣以來也可以節省開發所需的時間。

二、JavaBean開發要求

1.JavaBean本身就是一個類,屬於Java的面向對象編程。

2.在JSP中如果要應用JSP提供的Javabean的標籤來操作簡單類的話,則此類必須滿足如下的開發要求:

(1)所有的類必須放在一個包中,在WEB中沒有包的是不存在的;

(2)所有的類必須聲明爲public class,這樣才能夠被外部所訪問;

(3)類中所有的屬性都必須封裝,即:使用private聲明;

(4)封裝的屬性如果需要被外部所操作,則必須編寫對應的setter、getter方法;

(5)一個JavaBean中至少存在一個無參構造方法,此爲JSP中的標籤所使用。

三、JavaBean的內省操作
JDK中提供了對JavaBean進行操作的一些API,這套API就稱爲內省。所謂JavaBean的內省操作就是根據屬性名,對JavaBean進行讀寫。說上去很簡單,但是有很多細節,比方說JavaBean對屬性的命名有一定的規則,需要解析。有人會問那爲什麼不直接調用JavaBean的setXXX跟getXXX來讀寫屬性值,因爲JavaBean的應用領域大多在J2EE項目中,尤其突出的使用是在EL表達式中。我們可以通過級聯操作獲取屬性值例如“person.birthday.time”。這樣就沒法通過方法來獲取屬性值,只有通過內省,再通過反射調用方法讀寫屬性值。

四、編程實踐

(1)我寫了一個簡單的JavaBean對象,是一個Person對象,包含三個屬性,name,age,birthday,代碼如下:

package cn.rocket.study.introspector;

import java.sql.Date;

/**
 * @author rocket
 *
 */
public class Person {
    private String name ;
    private Integer age ;
    private Date birthday = new Date(System.currentTimeMillis()) ;



    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    public Person(String name,Integer age){
        this.name = name ;
        this.age = age ;
    }
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }



}

(2)手動實現JavaBean的內省操作

package cn.rocket.study.introspector;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class IntrospectorTest {
    public static void main(String[] args) throws IntrospectionException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
        Person person = new Person("rocket", 20);
        System.out.println("原始數據是:"+person);

        String propertyName = "name" ;

        Object val = getProperty(person, propertyName);

        System.out.println("通過內省獲取JavaBean屬性:name = "+val);


        Object value = "Jack" ;
        setProperty(person, propertyName, value);
        System.out.println("通過內省設置JavaBean屬性後:name="+getProperty(person, propertyName));

    }

    //通過內省操作獲取JavaBean屬性值
    private static Object getProperty(Object obj, String propertyName)
            throws IntrospectionException, IllegalAccessException, InvocationTargetException {
        /*
        //使用比較簡單的方式 
        PropertyDescriptor proDescriptor = new PropertyDescriptor(propertyName,obj.getClass());
        Method getMethod = proDescriptor.getReadMethod() ;
        Object val = getMethod.invoke(obj);//通過反射調用方法
        return val;
        */

        //使用比較笨的方式
        Object returnVal = null ;
        BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass()) ;
        PropertyDescriptor[] pros = beanInfo.getPropertyDescriptors() ;
        for(PropertyDescriptor p:pros){
            if(p.getName().equals(propertyName)){
                returnVal = p.getReadMethod().invoke(obj);
                break ;
            }
        }
        return returnVal ;
    }

    //通過內省操作設置JavaBean屬性值
    private static void setProperty(Object obj, String propertyName, Object value)
            throws IntrospectionException, IllegalAccessException, InvocationTargetException {
        PropertyDescriptor proDescriptor = new PropertyDescriptor(propertyName,obj.getClass());
        Method setMethod = proDescriptor.getWriteMethod() ;//通過反射調用方法
        setMethod.invoke(obj, value);
    }
}

這裏寫圖片描述

(3)好在apache給我們提供了一個JavaBean內省操作的工具包,叫BeanUtils,當然他依賴apache旗下的log包,工具包如下:
這裏寫圖片描述

下面是我使用BeanUtils操作JavaBean屬性的源代碼,BeanUtils功能很強大,不僅可以操作JavaBean屬性,而且可以將Map轉化成JavaBean對象,將JavaBean對象轉換成Map對象,由於篇幅有限,讀者可以自行實踐:

package cn.rocket.study.introspector;

import java.lang.reflect.InvocationTargetException;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;

public class BeanUtilsTest {
    public static void main(String[] args) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException{
        Person person = new Person("rocket", 12);
        BeanUtils.setProperty(person, "birthday.time", "222");
        System.out.println(person.getBirthday());
        Map<String, Object> map = BeanUtils.describe(person);
        System.out.println(map);
    }
}

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章