zoukankan      html  css  js  c++  java
  • Java内省

    什么是内省?

      Java语言对bean类属性、事件的一种缺省处理方法,例如类A中有属性name,那我们可以通过getName,setName来得到其值或者设置新的值

    什么是JavaBean?

      JavaBean 是一种JAVA语言写成的可重用组件。为写成JavaBean,类必须是具体的和公共的,并且具有无参数的构造器。JavaBean 通过提供符合一致性设计模式的公共方法将内部域暴露成员属性。众所周知,属性名称符合这种模式,其他Java 类可以通过自身机制发现和操作这些JavaBean 属性。

    下面这个Person类就是一个JavaBean,大家参考一下:

    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的属性描述类。

        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"));
        }
    }

          

          

      

  • 相关阅读:
    前端Tips#3
    前端Tips#2
    图算法
    【Javascript】重新绑定默认事件
    【Yeoman】热部署web前端开发环境
    添加远程链接MySQL的权限
    background-clip 背景图片做适当的裁剪
    linux系统下将php和mysql命令加入到环境变量中的方法
    background-size 设置背景图片的大小
    multiple backgrounds 多重背景
  • 原文地址:https://www.cnblogs.com/Ray-xujianguo/p/3355794.html
Copyright © 2011-2022 走看看