工学1号馆

home

« | 返回首页 | »

java核心系列14-内省

By Wu Yudong on June 14, 2015

原创文章,转载请注明: 转载自工学1号馆

内省(Introspector) 是Java 语言对 JavaBean 类属性、事件的一种缺省处理方法。

JavaBean简介

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

为什么要使用JavaBean 

在实际的开发过程中,通常会出现重复的代码或者段落,此时就会大大降低程序的可重用性并且浪费时间。使用JavaBean就可以大大简化程序的设计过程并且方便了其它程序的重复使用。

JavaBean在服务器端的应用具有非常强大的优势,非可视化的JavaBean可以非常好地实现控制逻辑、业务逻辑、表示层之间的分离,从而大大降低了它们之间的耦合度。非可视化的JavaBean现在多用于后台处理,这样会使系统具有一定的灵活性。

JavaBean是Java程序的一种,所使用的语法和其它类似的Java程序一致。在程序中使用JavaBean具有以下优点:

(1)可以实现代码的重复利用。

(2)易编写、易维护、易使用。

(3)它可以压缩在jar文件中,以更小的体积在网络中应用

(4)完全是Java语言编写,可以在任何安装了Java运行环境的平台上的使用,而不需要重新编译。

JavaBean的形式和要素

编写JavaBean就是编写一个Java的类,这个类创建的一个对象称做一个Bean。为了能让使用这个bean的应用程序构建工具(比如JSP引擎)知道这个bean的属性和方法,只需在类的方法命名上遵守以下规则:

(1)如果类的成员变量的名字是xxx,那么为了更改或获取成员变量的值,即更改或获取属性,在类中可以使用两个方法:

  • getXXX():用来获取属性xxx。
  • setXXX():用来修改属性xxx.。

(2)对于boolean类型的成员变量,即布尔逻辑类型的属性,允许使用"is"代替上面的"get"和"set"。

(3)类中方法的访问属性都必须是public的。

(4)类中如果有构造方法,那么这个构造方法也是public的并且没有参数。

JavaBean示例:

import java.io.Serializable;
public class JavaBeanDemo implements Serializable{
    private int id;
    private String name;
    
    JavaBeanDemo(){}
    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;
    }
}

如果要在两个模块之间传递多个信息,可以将这些信息封装到一个JavaBean中,这种JavaBean的实例对象通常称之为值对象(Value Object,简称VO)。这些信息在类中用私有字段来存储,如果读取或设置这些字段的值,则需要通过一些相应的方法来访问,JavaBean的属性是根据其中的setter和getter方法来确定的,而不是根据其中的成员变量。如果方法名为setId,中文意思即为设置id,如果方法名为getId,中文意思即为获取id。去掉set前缀,剩余部分就是属性名,如果剩余部分的第二个字母是小写的,则把剩余部分的首字母改成小的。

按照这样的规则,可以得出下面的实例:

setId()的属性名-->id

isLast()的属性名-->last

setCPU的属性名是什么?-->CPU

getUPS的属性名是什么?-->UPS

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

一个符合JavaBean特点的类可以当作普通类一样进行使用,但把它当JavaBean用肯定需要带来一些额外的好处,我们才会去了解和应用JavaBean!好处如下:

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

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

java内省实战

1、实现用eclipse自动生成 ReflectPoint类的setter和getter方法。

public class ReflectPoint {
	private int x;
	private int y;
	
	public ReflectPoint(int x, int y) {
		this.x = x;
		this.y = y;
	}
	public int getX() {
		return x;
	}
	public void setX(int x) {
		this.x = x;
	}
	public int getY() {
		return y;
	}
	public void setY(int y) {
		this.y = y;
	}
}

获得属性x的值并且设置x的值:

import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;

public class ReflectTest2 {
	public static void main(String[] args) throws Exception{
		ReflectPoint pt1 = new ReflectPoint(1, 2);
		String propertyName = "x"; 
		//直接调用JavaBean API
		PropertyDescriptor pd = new PropertyDescriptor(propertyName, pt1.getClass());
		Method methodGetX = pd.getReadMethod();
		Object retVal = methodGetX.invoke(pt1);
		System.out.println(retVal);
		
		Method methodSetX = pd.getWriteMethod();
		methodSetX.invoke(pt1, 3);
		System.out.println(pt1.getX());
	}
}

小技巧:用eclipse将读取属性和设置属性的流水帐代码分别抽取成方法,选中代码,右键选择--Refactor-->ExtractMothod-->...  重构后的代码如下:

private static void setProperty(ReflectPoint pt1, String propertyName,
		Object value) throws IntrospectionException,
		IllegalAccessException, InvocationTargetException {
	PropertyDescriptor pd2 = new PropertyDescriptor(propertyName, pt1.getClass());
	Method methodSetX = pd2.getWriteMethod();
	methodSetX.invoke(pt1, value);
}
private static Object getProperty(Object pt1,
		String propertyName) throws IntrospectionException,
		IllegalAccessException, InvocationTargetException {
	PropertyDescriptor pd = new PropertyDescriptor(propertyName, pt1.getClass());
	Method methodGetX = pd.getReadMethod();
	Object retVal = methodGetX.invoke(pt1);
	System.out.println(retVal);
	return pd;
}

2、修改上面的代码,采用遍历BeanInfo的所有属性方式来查找和设置某个RefectPoint对象的x属性。

思路:在程序中把一个类当作JavaBean来看,就是调用IntroSpector.getBeanInfo方法, 得到的BeanInfo对象封装了把这个类当作JavaBean看的结果信息。代码如下:

private static Object getProperty(Object pt1,
		String propertyName) throws IntrospectionException,
		IllegalAccessException, InvocationTargetException {
	BeanInfo beanInfo = Introspector.getBeanInfo(pt1.getClass());
	PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
	Object retVal = null;
	for(PropertyDescriptor pd : pds) {
		if(pd.getName().equals(propertyName)) {
			Method methodGetX = pd.getReadMethod();
			retVal = methodGetX.invoke(pt1);
			break;
		}
	}
	return retVal;
}

如果文章对您有帮助,欢迎点击下方按钮打赏作者

Comments

No comments yet.
To verify that you are human, please fill in "七"(required)