【Java EE 学习 23】【log4j的使用】【ant的使用】【内省】

一、ant下载地址:http://ant.apache.org/bindownload.cgi 

二、log4j下载地址:http://logging.apache.org/log4j/2.x/download.html

三、内省

  1.什么是内省。

    本质上是反射,具体技术由sun替公司提供,集成到了jdk中,可以根据字段名称(String)和字节码对象得到该字段的一个描述:PropertyDescriptor,并由此得到该字段的get、set方法(Method)。

  将要使用的JavaBean

 1 package com.kdyzm.domain;
 2 
 3 import java.util.Date;
 4 
 5 public class Person {
 6     private String name;
 7     private Integer age;
 8     private Date date;
 9     
10     public Person(String name, Integer age, Date date) {
11         this.name = name;
12         this.age = age;
13         this.date = date;
14     }
15     public String getName() {
16         return name;
17     }
18     public void setName(String name) {
19         this.name = name;
20     }
21     public Integer getAge() {
22         return age;
23     }
24     public void setAge(Integer age) {
25         this.age = age;
26     }
27     public Date getDate() {
28         return date;
29     }
30     public void setDate(Date date) {
31         this.date = date;
32     }
33     public Person() {
34     }
35     @Override
36     public String toString() {
37         return "Person [name=" + name + ", age=" + age + ", date=" + date + "]";
38     }
39 }

  2.核心类:

    (1)PropertyDescriptor类。

        [1]继承关系

            java.lang.Object

              |--java.beans.FeatureDescriptor

                |--java.beans.PropertyDescriptor

        [2]构造方法

构造方法摘要

PropertyDescriptor(String propertyName, Class<?> beanClass)
          通过调用 getFoo 和 setFoo 存取方法,为符合标准 Java 约定的属性构造一个 PropertyDescriptor。

 

PropertyDescriptor(String propertyName, Class<?> beanClass, String readMethodName, String writeMethodName)
          此构造方法带有一个简单属性的名称和用于读写属性的方法名称。

 

PropertyDescriptor(String propertyName, Method readMethod, Method writeMethod)
          此构造方法带有某一简单属性的名称,以及用来读取和写入属性的 Method 对象。

 

         [3]核心方法

 Class<?>

getPropertyType()
          获得属性的 Class 对象。

 Method

getReadMethod()
          获得应该用于读取属性值的方法。

 Method

getWriteMethod()
          获得应该用于写入属性值的方法。

void

setReadMethod(Method readMethod)
          
设置应该用于读取属性值的方法。

 void

setWriteMethod(Method writeMethod)
          
设置应该用于写入属性值的方法。

        [4]使用示例。

          获的setName方法并给Person对象赋值。

public void test1() throws Exception
    {
        Person p=new Person();
        /*
         //这里是通过普通的反射方法来实现的。
                Method method=p.getClass().getMethod("setName", String.class);
                method.invoke(p, "张三");
                System.out.println(p);
        */
        //下面通过使用内省的方式来实现该目的。
        PropertyDescriptor pd=new PropertyDescriptor("name", p.getClass(),"getName","setName");
        Method getName=pd.getReadMethod();
        String name=(String) getName.invoke(p);
        System.out.println(name);
        
        Method setName=pd.getWriteMethod();
        setName.invoke(p, "小强");
        getName=pd.getReadMethod();
        System.out.println(getName.invoke(p));
        /*
         * 输出结果:
         * null
         * 小强
         */
    }

        不能进行类型的自动转换。

public void test2() throws Exception
    {
        Person p=new Person();
        PropertyDescriptor pd=new PropertyDescriptor("age", p.getClass());
        Method setAge=pd.getWriteMethod();
        setAge.invoke(p, "12");//这里只能传递整数类型的参数,所以一定会报错!
        System.out.println(p);
    }

    (2)BeanInfo接口:专门分析一个JavaBean有多少属性,有哪些属性

      [1]获取该接口实例的方法

        使用Introspector(内省)类(   java.lang.Object   )的静态方法:getBeanInfo(Class<?> beanClass)

                        |--java.bean.Introspector

static BeanInfo

getBeanInfo(Class<?> beanClass)
          在 Java Bean 上进行内省,了解其所有属性、公开的方法和事件。

      [2]核心方法:getPropertygetDescriptors方法。 

PropertyDescriptor[]

getPropertyDescriptors()
          获得 beans PropertyDescriptor。

      [3]使用方法。

/*
     * 测试非常不好的类:BeanInfo类,该类并不会将一个Bean对象的所有属性都能解析成功,反而是只要是
     * get或者set方法都会
     * 解析出来。
     * 所以即使是getClass方法该类也会将其作为class属性解析出来。
     * 如果不成对,也会解析出来。
     */
    @Test
    public void test3() throws Exception
    {
        BeanInfo beaninfo=Introspector.getBeanInfo(Person.class);
        PropertyDescriptor pd[]=beaninfo.getPropertyDescriptors();
        for(int i=0;i<pd.length;i++)
        {
            String name=pd[i].getName();
            System.out.println(name);
        }
    }
    

  3.解决类型不匹配的方法:遍历判断

    (1)场景:Person类有age成员变量,为int类型,如果想要传递一个字符串给它,一般情况下会报错:不匹配的参数类型。怎样解决这个问题呢?对set方法能接受的参数类型进行判断,如果是整型参数才传递。

    (2)手动遍历解决。

/*
     * 怎样实现将字符串传递到setAge方法中
     * 通过使用便利的方式依次对set方法进行遍历
     * 这里的JavaBean必须是Integer类型的,否则不识别。
     * 这么麻烦的工作apache已经将其简化开发出了第三方jar包:BeanUtils.jar
     */
    @Test
    public void test4() throws Exception, IllegalArgumentException, IllegalAccessException, InvocationTargetException
    {
        String name="小强";
        String age="30";
        Person p=new Person();
        Method methods[]=p.getClass().getDeclaredMethods();
        for(Method method:methods)
        {
            String methodname=method.getName();
            //如果是set方法才行进下一步,get方法直接跳过
            if(methodname.startsWith("set"))
            {
                Class<?> clazz[]=method.getParameterTypes();
                System.out.println(clazz[0]);
                if(clazz[0].equals(String.class))
                {
                    method.invoke(p,name);
                }
                else if(clazz[0].equals(Integer.class))
                {
                    method.invoke(p, Integer.parseInt(age));
                }
            }
            else
                continue;
        }
        System.out.println(p);
    }

  4.使用第三方jar包:BeanUtils.jar解决 3  中的问题以及使用第三方jar包的好处。

  BeanUtils.jar下载地址:http://commons.apache.org/proper/commons-beanutils/download_beanutils.cgi

  依赖包:commons-logging.jar包

    (1)BeanUtils.jar是干什么用的?

       是一个处理JavaBean的工具包,内部也是使用内省,但是对内省进行了加强。

    (2)使用该工具包的好处是什么?

       JavaBean中的get方法和set方法不用再成对出现。

       能够自动进行基本数据类型的转换(不是基本数据类型不能自动进行转换)。

    (3)演示使用BeanUtils设置值。

//演示使用BeanUtils设置值
    @Test
    public void setValueTest() throws Exception, Exception
    {
        Person p=new Person();
        BeanUtils.setProperty(p,"name", "小强");
        BeanUtils.setProperty(p, "age", "45");
        BeanUtils.setProperty(p, "date", new Date());
        System.out.println(p);
    }

    (4)演示使用BeanUtils获取值。

//演示使用BeanUtils获取值。
    @Test
    public void getValueTest() throws IllegalAccessException, InvocationTargetException, NoSuchMethodException
    {
        Person p=new Person("小强",24,new Date());
        System.out.println(BeanUtils.getProperty(p, "name"));
        System.out.println(BeanUtils.getProperty(p, "age"));
        System.out.println(BeanUtils.getProperty(p, "date"));
    }

    (5)使用BeanUtils一次性将获取到的值封装到javaBean中。

//使用Benutils一次性填入所有值的方法
    @Test
    public void  setValueAll() throws Exception, InvocationTargetException
    {
        Person p=new Person();
        Map<String,Object>map=new HashMap<String,Object>();
        map.put("name", "小强");
        map.put("age", "24");
        map.put("date", new Date());
        BeanUtils.populate(p, map);            //这句是关键
        System.out.println(p);
        
        //这种方式在分析表单提交的数据并封装成JavaBean的时候使用的非常广泛,因为可以大大节省代码量,注意要使用request对象的getParameterMap()方法。
    }

 

posted @ 2015-06-29 20:03  狂盗一枝梅  阅读(419)  评论(0编辑  收藏  举报