JDK 之 Java Bean 內省機制

JDK 之 Java Bean 內省機制

JDK 規範目錄(http://www.javashuo.com/article/p-wdnembkc-ex.html)html

JavaBean 是一種特殊的 Java 類,主要用於傳遞數據信息,這種 Java 類中的方法主要用於訪問私有的字段,且方法名符合某種命名規則。java

1、JavaBean

1.1 JavaBean 命名規則

  1. 一個 JavaBean 類中的方法,去掉 set 或 get 前綴,剩餘部分就是屬性名,若是剩餘部分的第二個字母是小寫的,則把剩餘部分的首字母改爲小的。apache

    getAge/setAge --> age
    gettime --> time
    setTime --> timeide

  2. 若是去掉前綴,剩餘部分的第二個字母爲大寫,則所有大寫工具

    getCPU --> getCPUui

1.2 什麼叫作內省?

Java 內省主要使用來對 JavaBean 進行操做的,因此當一個類知足了 JavaBean 的條件,就可使用內省的方式來獲取和操做 JavaBean 中的字段值。內省提供了操做 JavaBean 的 API。code

Java 中提供了一套 API 用來訪問某個屬性的 getter/setter 方法,經過這些 API 可使你不須要了解這個規則,這些 API 存放於包 java.beans 中,通常的作法是經過類 Introspector 的 getBeanInfo 方法 來獲取某個對象的 BeanInfo 信息,而後經過 BeanInfo 來獲取屬性的描述器(PropertyDescriptor),經過這個屬性描述器就能夠獲取某個屬性對應的 getter/setter 方法,而後咱們就能夠經過反射機制來調用這些方法。orm

2、JDK 內省機制

2.1 Introspector 類

Introspector 這個類位於 java.beans 包中,該類中的方法都是靜態的,能夠直接使用類名調用。htm

// 獲取 beanClass 及其全部父類的 BeanInfo
BeanInfo getBeanInfo(Class<?>beanClass)

// 獲取 beanClass 及其指定到父類 stopClass 的 BeanInfo 
BeanInfo getBeanInfo(Class<?> beanClass, Class<?> stopClass)

咱們可使用 Introspector 的 getBeanInfo(Class<?> beanClass) 來獲取一個 JavaBean 類的 BeanInfo 對象。BeanInfo 有三個經常使用的屬性:對象

// bean 信息
BeanDescriptor beanDescriptor = beanInfo.getBeanDescriptor();
// 屬性信息
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
// 方法信息
MethodDescriptor[] methodDescriptors = beanInfo.getMethodDescriptors();

2.2 PropertyDescriptor 類

這個類位於 java.beans 包中。

@Test
public void test() throws Exception {
    PropertyDescriptor pd = new PropertyDescriptor("id", User.class);
    System.out.println(pd.getName());
}

2.3 PropertyEditor 類

Spring 中使用 PropertyEditor 向 JavaBean 中注入屬性。

@Test
public void test1() throws Exception {
    User user = new User();

    PropertyDescriptor propertyDescriptor = new new PropertyDescriptor("id", User.class);
    propertyDescriptor.setPropertyEditorClass(IntPropertyEditor.class);
    PropertyEditor propertyEditor = propertyDescriptor.createPropertyEditor(user);

    propertyEditor.setAsText("99");
    Method writeMethod = propertyDescriptor.getWriteMethod();
    writeMethod.invoke(user, propertyEditor.getValue());

    System.out.println(user);
}

@Test
public void test2() throws Exception {
    User user = new User();

    PropertyDescriptor propertyDescriptor = new new PropertyDescriptor("id", User.class);
    propertyDescriptor.setPropertyEditorClass(IntPropertyEditor.class);
    PropertyEditor propertyEditor = propertyDescriptor.createPropertyEditor(user);

    // 這個 evt 實際上就是 propertyEditor 對象
    propertyEditor.addPropertyChangeListener(evt -> {
        PropertyEditor source = (PropertyEditor) evt.getSource();
        Method writeMethod = propertyDescriptor.getWriteMethod();
        writeMethod.invoke(user, source.getValue());
    });
    propertyEditor.setAsText("99");
    System.out.println(user);
}

// JDK 中的 PropertyEditor 接口
public static class IntPropertyEditor extends PropertyEditorSupport {
    @Override
    public void setAsText(String text) throws IllegalArgumentException {
        setValue(Integer.parseInt(text));
    }
}

3、Apache BeanUtils 工具包

Apache 組織開發了一套用於操做 JavaBean 的 API(內省)。該工具在 commons-beanutils 包中,核心類 BeanUtils:

setProperty(bean, name, value)
copyProperties(target, source)

能夠支持 String 到 8 中基本數據類型轉換,其餘引用數據類型都須要註冊轉換器 ConvertUtils.register(Converter, Class)

使用 BeanUtils 來格式化日期:

public static void main(String[] args) throws Exception {
        
    User user = new User();
    
    String name = "zhangsan";
    String birthday = "19801122";
    
    // 註冊一個轉換器
    /* 使用匿名內部類來註冊轉換器
    ConvertUtils.register(new Converter() {
        
        public Object convert(Class beanClass, Object value) {
            String birthday = (String) value;
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
            try {
                return sdf.parse(birthday);
            } catch (ParseException e) {
                return null;
            }
        }
    }, Date.class);
    */
   
    DateConverter converter = new DateConverter();
    converter.setPatterns(new String[]{"yyyy-MM-dd","yyyyMMdd","MM/dd/yyyy"});
    ConvertUtils.register(converter, Date.class);
    
    BeanUtils.setProperty(user, "name", name);
    BeanUtils.setProperty(user, "birthday", birthday);

    System.out.println(user);  
}

參考:

  1. 《JavaBean 以及內省技術詳解》:https://www.cnblogs.com/yejiurui/archive/2012/10/06/2712693.html

天天用心記錄一點點。內容也許不重要,但習慣很重要!

相關文章
相關標籤/搜索