Java 基础加强 - JavaBean与内省操作

Java基础加强JavaBean与内省操作

一.JavaBean

1.     什么叫做JavaBean?

JavaBean是一种特殊的Java类,主要用于传递数据信息,这种Java类中的方法主要用于访问私有的字段,且方法名符合某种命名规则。

 

2.     JavaBean如此特殊,特殊之处在哪里?

A.     如果读取或设置某个类对象上的私有字段的值,则需要通过一些相应的方法来访问,通常会想到使用getter和setter方法来操作。例如有个方法叫做getName(),那么我们就可以知道,通过方法名字我们知道,这个方法使用来获取name属性的值的,所以name是一个私有的字段(属性);同理setName()当然是用来设置name属性的值的,依然反馈出name是一个私有的属性,显然这中方法的命名是很健壮的,所以JavaBean中的方法都是具有特定的命名规则,这样一个类中有这样的命名方法的方法,就可以当作JavaBean来使用。

B.     除此之外,我们知道具有JavaBean特点的类,除了方法有一些特殊的命名规则外,其实和普通类一样,所以我们也可以将其当作普通的类来使用。

C.     总之,一个类被当作javaBean使用时,JavaBean的属性是根据方法名推断出来的,它根本看不到Java类内部的成员变量。

 

3.     JavaBean方法命名规则细节说明

A.      一个JavaBean类中的方法,去掉set或get前缀,剩余部分就是属性名,如果剩余部分的第二个字母是小写的,则把剩余部分的首字母改成小的。

getAge/setAge-->age

gettime-->time

setTime-->time

B.      如果去掉前缀,剩余部分的第二个字母为大写,则全部大写

getCPU-->CPU。

 

4.     JavaBean作用

A.    如果要在两个模块之间传递多个信息,可以将这些信息封装到一个JavaBean中,这种JavaBean的实例对象通常称之为值对象(Value Object,简称VO),这些信息在类中用私有字段来存储。

B.     在Java EE开发中,经常要使用到JavaBean。很多环境就要求按JavaBean方式进行操作。

C.     JDK中提供了对JavaBean进行操作的一些API,这套API就称为内省。如果要你自己去通过getX方法来访问私有的x,怎么做,有一定难度吧?用内省这套api操作JavaBean比用普通类的方式更方便。

 

 

二.内省操作

1.     什么叫做内省?

英文Introspector,名为内窥镜,内部检查,内省主要使用来对JavaBean进行操作的,所以当一个类满足了JavaBean的条件,就可以使用内省的方式来获取和操作JavaBean中的字段值。内省提供了操作JavaBean的API。

2.      JavaBean复杂内省操作

Java 中提供了一套 API 用来访问某个属性的getter/setter 方法,通过这些 API 可以使你不需要了解这个规则,这些 API 存放于包 java.beans 中,一般的做法是通过类Introspector 的getBeanInfo方法 来获取某个对象的BeanInfo 信息,然后通过BeanInfo 来获取属性的描述器(PropertyDescriptor),通过这个属性描述器就可以获取某个属性对应的getter/setter 方法,然后我们就可以通过反射机制来调用这些方法。

 

A.     Introspector类

Introspector这个类位于Java.beans包中,该类中的方法都是静态的,可以直接使用类名调用。

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

我们可以使用IntrospectorgetBeanInfo(Class<?> beanClass)来获取一个JavaBean类的BeanInfo对象,然后通过BeanInfo对象的getPropertyDescriptors()方法获取属性描述器PropertyDescriptor对象的数组,通过遍历数组,可以获取到每个字段相对应的属性描述,通过描述器去获取设置和获取字段值的方法。

import java.beans.BeanDescriptor;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class JavaBeanDemo1
{
	public static void main(String[] args) throws Exception
	{
		  NoteBook myNoteBook = new NoteBook("Lenovo G470", 4800);
//通过Introspector的getBeanInfo方法获取BeanInfo对象
		 BeanInfo info = Introspector.getBeanInfo(myNoteBook.getClass());
//通过BeanInfo对象获取属性描述器对象数组
		  PropertyDescriptor[] pds = info.getPropertyDescriptors();
		  setProperty(myNoteBook, pds);
		  getProperty(myNoteBook, pds);
	}

public static void getProperty(NoteBook myNoteBook, PropertyDescriptor[] pds)
throws Exception
	{
//通过遍历PropertyDescriptor[]数组,获取属性的获取值方法,并获取值。
		for(PropertyDescriptor pd : pds )
		  {
//打印属性的Class类型
		        System.out.println(pd.getPropertyType());
//打印声明这个属性的类Class
System.out.println( pd.getReadMethod().getDeclaringClass());
			  if("name".equals(pd.getName()))
			  {
//获取这个属性值读取方法,并执行打印
				  Method nameGet = pd.getReadMethod();
				  System.out.println(nameGet.invoke(myNoteBook));
			  }
			  if("price".equals(pd.getName()))
			  {
				  Method priceGet = pd.getReadMethod();
				  System.out.println(priceGet.invoke(myNoteBook));
			  }
		  }
	}

public static void setProperty(NoteBook myNoteBook, PropertyDescriptor[] pds)
			throws Exception
	{
//通过遍历PropertyDescriptor[]数组,获取属性的获取值方法,并获取值。 	
		for(PropertyDescriptor pd : pds)
		  {
			    if("name".equals(pd.getName()))
			    {
//设置这个属性值读取方法
			    	    Method nameSet = pd.getWriteMethod();
			    	    nameSet.invoke(myNoteBook,"Asus" );
			    }
			    if("price".equals(pd.getName()))
			    {
			    	Method priceSet = pd.getWriteMethod();
			    	priceSet.invoke(myNoteBook, 6000);
			    }
	      }
	}

}

class NoteBook
{
	 private String name ;
	 private int price;
	 public NoteBook(String name , int price)
	 {
		 this.name = name ;
		 this.price = price;
	 }
	 public void setName(String name )
	 {
		 this.name = name;
	 }
	 public String getName()
	 {
		 return this.name;
	 }
	 public void setPrice(int price)
	 {
		 this.price = price;
	 }
	 public int getPrice()
	 {
		 return this.price;
	 }
	 public String getX()
	 {
		 return "";
	 }
}

B.    PropertyDescriptor类

这个类位于java.beans包中,该类提供了三个构造方法,如下:
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 对象。
通常我们只是用第一个构造方法,方便使用。
 
实例1: 
<span style="font-size:14px">import java.beans.PropertyDescriptor;
public class PropertyDescriptorDemo
{
	public static void main(String[] args)throws Exception
	{
		Person p = new Person("Kandy",25);
		PropertyDescriptor pd = new PropertyDescriptor("name",p.getClass());
      System.out.println(  pd.getName());//打印属性名
      System.out.println(pd.getDisplayName());//打印属性名
     System.out.println( pd.getPropertyType());//获取属性类型
	}
}</span>
执行结果:

name

name

class java.lang.String
示例2:

<span style="font-size:14px">importjava.beans.PropertyDescriptor;
importjava.lang.reflect.Method;
public class PropertyDescriptorDemo
{
       public static voidmain(String[] args)throwsException
       {
              Person p = newPerson("Kandy",25);
              //构建一个name属性的属性描述器
              PropertyDescriptor pd = newPropertyDescriptor("name",p.getClass());
              //通过属性描述器获取属性值设置方法
       Method methodWrite = pd.getWriteMethod();
        methodWrite.invoke(p,"Ansen");
      //通过属性描述器获取属性值获取方法
        Method methodRead = pd.getReadMethod();
       Object value = methodRead.invoke(p);
       System.out.println(value);
       }
}</span>

执行结果为:Ansen

3.     开源扩展BeanUtils工具包

BeanUtils等工具包都是由阿帕奇提供的,为了便于开发。BeanUtils可以将8种基本数据类型进行自动的转换,也就是一字符串形式给,以字符串形式体现出来,因此对于非基本数据类型,就需要注册转换器Converter,这就需要ConverUtils包。

好处:

A.     提供的set或get方法中,传入的是字符串,返回的还是字符串,因为在浏览器中,用户输入到文本框的都是以字符串的形式发送至服务器上的,所以操作的都是字符串。也就是说这个工具包的内部有自动将整数转换为字符串的操作。

B.     支持属性的级联操作,即支持属性链。如可以设置:人的脑袋上的眼睛的眼珠的颜色。这种级联属性的属性连如果自己用反射,那就很困难了,通过这个工具包就可以轻松调用。

注意:

要使用BeanUtils,就要将BeanUtils包添加到build path中,注意如果要正常使用,还要将还要将Apache公司的logging(日志)的jar包也添加进BuildPath。

在工程中导入工具jar包

两种方式:

A.     右键项目--选择Properties---Java Build Path--选择Liberiers标签。AddExternal Jars--选择要导入的jar包。即可。这样做有个问题就是如果jar路径发生变化。项目就不能使用到这个jar包。

B.     在项目中建立一个lib目录,专门用于存放项目所使用到的jar工具包。将要使用到jar包复制粘贴进来,并在jar上点右键--选择Builder Path---Add to BiuldPath,即可。这时jar包中的对象,就可以使用了。这样做的好处à项目移动,jar随项目移动。

 

实例代码1:

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;
public class BeanUtilsDemo1
{
   public static void main(String[] args) throws Exception
   {
      Person p1 = new Person("Ansen", 24);
//使用BeanUtils的setProperty方法为p1对象的name和age属性设置值       BeanUtils.setProperty(p1,"name","Kandy");
BeanUtils.setProperty(p1,"age","25");
//使用BeanUtils的getProperty方法获取p1对象的name和age属性值
Object obj1 = BeanUtils.getProperty(p1,"name");
Object obj2 = BeanUtils.getProperty(p1,"age");
System.out.println(obj1);
System.out.println(obj2);
}
}

 BeanUtils包中其他的Bean操作类

BeanUtils包中还有一个工具类PropertyUtils,用法跟BeanUtils一样。区别:

A.     BeanUtils会对JavaBean的属性的类型进行转换,如属性本身是integer,会转换为String。

B.     PropertyUtils以属性本身的类型进行操作。

 

实例1:

               Person p = new Person("ZHG",24);
		Object myName = PropertyUtils.getProperty(p,"name");
		System.out.println(myName);
		PropertyUtils.setProperty(p,"age",23);
		Object myAge = PropertyUtils.getProperty(p,"age");
		System.out.println(myAge);
	    PropertyDescriptor d1 = PropertyUtils.getPropertyDescriptor(p,"name");
	    Method setMethod = d1.getWriteMethod();
	    setMethod.invoke(p,"张先生");
	  	Method getMethod  = d1.getReadMethod() ;
		System.out.println(getMethod.invoke(p));








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值