Java內省

什麼是內省?java

  Java語言對bean類屬性、事件的一種缺省處理方法,例如類A中有屬性name,那咱們能夠經過getName,setName來獲得其值或者設置新的值數據庫

什麼是JavaBean?設計模式

  JavaBean 是一種JAVA語言寫成的可重用組件。爲寫成JavaBean,類必須是具體的和公共的,而且具備無參數的構造器。JavaBean 經過提供符合一致性設計模式的公共方法將內部域暴露成員屬性。衆所周知,屬性名稱符合這種模式,其餘Java 類能夠經過自身機制發現和操做這些JavaBean 屬性。數組

下面這個Person類就是一個JavaBean,你們參考一下:app

public class Person {

    private int id;
    private String name;
    
    public Person() {
    }
    
    public Person(int id, String name) {
        this.id = id;
        this.name = name;
    }
    
    public int getId() {
        return id;
    }
    
    public void setId(int id) {
        this.id = id;
    }
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
}

  Java中提供了一套API來處理JavaBean,也就是內省(Introspector)機制的核心,這些處理類位於java.beans目錄下,下面咱們來了解一下: 框架

PropertyDescriptor類:工具

  Introduction:能夠叫這個類做屬性描述類,也就是能夠經過這個類去描述咱們想要操做的類。學習

  Methods:測試

    public PropertyDescriptor(String propertyName, Class<?> beanClass):propertyName就是JavaBean中的屬性,像上面那樣Person類中的「id」,beanClass就是JavaBean類了,像Person類,咱們經過getClass方法就能夠拿到該類的Class了,這個構造方法獲得了該JavaBean的屬性描述類。this

    public Method getReadMethod():獲取用於讀取屬性值的方法,例如經過這個方法就能夠拿到「id」的getId方法。

    public Method getWriteMethod():獲取用於寫入屬性值的方法,例如經過這個方法就能夠拿到「id」的setId方法。

    注意:上面兩個方法的返回值是Method,要操做方法的話須要經過invoke方法來調用。

@SuppressWarnings("all")
public class TestPropertyDescriptor {

    private static Person person;
    
    @BeforeClass
    public static void init() {
        person = new Person(1, "xujianguo");
    }
    
    @Test
    public void testGetProperty() throws Exception {
        PropertyDescriptor pd = new PropertyDescriptor("id", person.getClass());
        Method method = pd.getReadMethod();
        Object id = method.invoke(person, null);
        System.out.println(id);
    }
    
    @Test
    public void testSetProperty() throws Exception {
        PropertyDescriptor pd = new PropertyDescriptor("id", person.getClass());
        Method method = pd.getWriteMethod();
        method.invoke(person, 3);
        testGetProperty();
    }
}

上面的testGetProperty方法能夠拿到id的值,testSetProperty方法能夠設置id的值,而後經過testGetProperty方法打印出id的值。

Introspector類:

  Introduction:Introspector 類爲經過工具學習有關受目標 Java Bean 支持的屬性、事件和方法的知識提供了一個標準方法。

  Method:

    public static BeanInfo getBeanInfo(Class<?> beanClass)在javabean上進行內省,瞭解該類的全部屬性、方法和事件,因此這個方法很重要。這個方法的返回值是BeanInfo類型的,下面咱們來看看這個類:

  BeanInfo類:

    Introduction:該類是一個能夠提供JavaBean各類信息的類。

    Method:

      public PropertyDescriptor[] getPropertyDescriptors():獲取bean的PropertyDescriptor,這個獲取的是一個數組,數組裏面裝的是各類屬性的屬性描述類,經過該方法就能夠找到咱們想要操做的那個方法。

@SuppressWarnings("all")
public class TestPropertyDescriptor {

    private static Person person;
    
    @BeforeClass
    public static void init() {
        person = new Person(1, "xujianguo");
    }

    @Test
    public void testOtherMethod() throws Exception {
        BeanInfo beanInfo = Introspector.getBeanInfo(person.getClass());
        PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
        Object value = null;
        for(PropertyDescriptor pd : pds) {
            if(pd.getName().equals("name")) {
                Method method = pd.getReadMethod();
                value = method.invoke(person, null);
                break;
            }
        }
        System.out.println(value);
    }
}

上面的例子在一個屬性描述類的數組中找到咱們要操做的name的方法,PropertyDescriptor的getName方法能夠拿到屬性名。

 

下面介紹BeanUtils工具包:

BeanUtils就是一個小小的框架,裏面封裝不少方法,讓咱們很方便的調用,爲所欲爲的操做JavaBean。

  BeanUtils.PropertyUtils:是這個工具包裏面很重要的一個類,這個類經過它的名字就能夠知道它操做的是JavaBean的屬性,在操做以前咱們首先理解property的幾種狀態:

  Simple:也就是Java的基礎類型,指property的屬性修飾符,如int、String,這些都是比較簡單的類型,咱們就能夠經過public static Object getSimpleProperty(Object bean, String name)方法拿到屬性值,用public static Object setSimpleProperty(Object bean, String name, Object value)設置屬性值。

  Indexed:這個屬性的狀態是針對List等集合的,若是屬性修飾符是List的話,就能夠經過public static Obejct getIndexedProperty(Object bean, String name, int index)方法拿到屬性值,用public static Obejct setIndexedProperty(Object bean, String name, int index, Object value)方法設置屬性值。

  Mapped:這個屬性的狀態是針對Map集合,由於Map的裏面的設置是key-value的關係,PropertyUtils類就用這個方法的key去拿Map中的value,便是經過public static Object getMappedProperty(Obejct bean, String name, String value)方法去拿key對應的value,經過public static Object setMappedProperty(Object bean, String name, String value, Object value)方法去設置key對應的value。

  Nested:這個就是用來解決比較複雜的屬性問題,如你的List裏面放置了Person,但你想拿出Person中的name屬性,怎麼辦呢?就是用這個方法了,經過public static Object getNestedProperty(Object bean, String name)拿出屬性值,經過public static Object setNestedProperty(Object bean, String name, Object value)去設置它的屬性值,可是你會說,這個跟前面的同樣啊,哈哈,是的,這個方法的特定即便在寫name的值的時候能夠經過「.」符號來層層拿出值,看下面的例子你就知道了。

首先定義一個JavaBean類:

@SuppressWarnings("rawtypes")
public class School {
    private int id;
    private String name;
    private List list;
    private Map map;
    private List<Person> personList;
    
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public List getList() {
        return list;
    }
    public void setList(List list) {
        this.list = list;
    }
    public Map getMap() {
        return map;
    }
    public void setMap(Map map) {
        this.map = map;
    }
    public List<Person> getPersonList() {
        return personList;
    }
    public void setPersonList(List<Person> personList) {
        this.personList = personList;
    }
}

下面就是測試類了:

 

@SuppressWarnings("all")
public class BeanUtilsDemo {
    
    private static School school;
    
    @Before
    public void initing() {
        school = new School();
        school.setId(1);
        school.setName("gdut");
        
        List list = new ArrayList();
        list.add("first");
        list.add("second");
        school.setList(list);
        
        Map map = new HashMap();
        map.put("xjg", "xujianguo");
        map.put("zyp", "zhouyanping");
        school.setMap(map);
        
        Person person = new Person(3, "RayGuo");
        List<Person> personList = new ArrayList<Person>();
        personList.add(person);
        school.setPersonList(personList);
    }
    
    @Test
    public void testSimpleGetProperty() throws Exception, NoSuchMethodException {
        int id = (Integer) PropertyUtils.getSimpleProperty(school, "id");
        String name = (String) PropertyUtils.getSimpleProperty(school, "name");
        System.out.println(id + "   " + name);
    }
    
    @Test
    public void testSimpleSetProperty() throws Exception {
        PropertyUtils.setSimpleProperty(school, "id", 2);
        PropertyUtils.setSimpleProperty(school, "name", "scut");
        testSimpleGetProperty();
    }
    
    @Test
    public void testIndexedGetProperty() throws Exception {
        String str = (String) PropertyUtils.getIndexedProperty(school, "list", 1);
        System.out.println(str);
    }
    
    @Test
    public void testIndexedSetProperty() throws Exception {
        PropertyUtils.setIndexedProperty(school, "list", 1, "secondsecond");
        testIndexedGetProperty();
    }
    
    @Test
    public void testMappedGetProperty() throws Exception {
        String name = (String) PropertyUtils.getMappedProperty(school, "map", "zyp");
        System.out.println(name);
    }
    
    @Test
    public void testMappedSetProperty() throws Exception {
        PropertyUtils.setMappedProperty(school, "map", "zyp", "zypzyp");
        testMappedGetProperty();
    }
    
    @Test
    public void testNestedGetProperty() throws Exception {
        String name = (String) PropertyUtils.getNestedProperty(school, "personList[0].name");
        System.out.println(name);
    }
    
    @Test
    public void testNestedSetProperty() throws Exception {
        PropertyUtils.setNestedProperty(school, "personList[0].name", "ApplePing");
        testNestedGetProperty();
    }
}

  

  BasicDynaClass和BasicDynaBean:兩個類是挺好用的東西來的,好比說你會遇到這種狀況,從數據庫拿到了一堆的數據,可是你不想寫一個Class,也就是定義一個實體類,這個咱們能夠採用這個類了,就是動態生成一個JavaBean,用這個JavaBean來操做這些數據,存儲這些數據,就不用寫死一個Class了,下面咱們來簡單瞭解一下怎麼用:

    DynaProperty類:從名字就能夠知道了,動態屬性,就是定義一個動態類有哪些屬性了

      method:public DynaProperty(String name, Class type):這是構造方法,經過該構造方法就能夠建立一個動態的屬性了

    BasicDynaClass類:這個就是動態類了,經過這個類建立一個咱們須要的動態類,在建立的時候固然要咱們前面定義的動態屬性加進入了。

      method:

        public BasicDynaClass(String name, Class dynaBeanClass, DynaProperty[] props):這個是它的構造方法,name是你要動態生成那個JavaBean的名字,dynaBeanClass就是指這個類的Class類型,props就是JavaBean的屬性集合了。

        public DynaBean newInstance():經過這個方法就能夠建立一個實例了。

    DynaBean類:動態的JavaBean

      method:

        Object set(String name, Object value):設置屬性的值

        Object get(String name):獲得屬性的值

Demo:

@SuppressWarnings("rawtypes")
public class DynaClassDemo {

    @Test
    public void test() throws Exception {
        DynaProperty prop1 = new DynaProperty("id", Integer.class);
        DynaProperty prop2 = new DynaProperty("name", String.class);
        DynaProperty prop3 = new DynaProperty("map", java.util.Map.class);
        DynaProperty[] prop = new DynaProperty[]{prop1, prop2, prop3};
        
        BasicDynaClass dynaClass = new BasicDynaClass("people", null, prop);
        DynaBean people = dynaClass.newInstance();
        people.set("id", 1);
        people.set("name", "xujianguo");
        people.set("map", new HashMap());
        
        System.out.println(people.get("id") + "   " + people.get("name"));
    }
}
相關文章
相關標籤/搜索