内省
内省是Java语言的一种重要特性。使用内省我们可以在运行时得到一个类的内部信息。这些信息包括方法、属性、构造函数及其他。内省的一个应用是开发使用插件的应用程序。应用程序可以在运行时获取并使用插件类的构造函数、方法和属性。内省也可以应用于创建Java Beans和Javadocs中。
Introspector类
Introspector类为访问目标Jave Bean支持的属性、事件和方法提供了标准方法。该方法可用于工具类(如BeanUtils)中。
对于属性、事件和方法中的每一类信息,Introspector会分别分析目标bean以及其父类,寻找显式或隐式信息并用其构建一个能够全面描述目标bean的BeanInfo对象。
通过调用Introspector.getBeanInfo()方法来获得指定类的bean信息。Java Bean规范允许通过实现BeanInfo接口,定义一个对象来描述bean。为了将BeanInfo与bean关联起来,须遵守如下命名模式:bean信息类的名字必须是将"BeanInfo"添加到bean名字的后面构成。例如:
package com.cwind.introspector; public class Ultraman extends Superhero { public String avanta ; public Ultraman(String avanta) { super (); this .avanta = avanta; } public String getAvanta() { return avanta ; } public void setAvanta(String avanta) { this .avanta = avanta; } }相关信息类:
package com.cwind.introspector; import java.beans.IntrospectionException; import java.beans.PropertyDescriptor; import java.beans.SimpleBeanInfo; public class UltramanBeanInfo extends SimpleBeanInfo { public PropertyDescriptor[] getPropertyDescriptors() { try { return new PropertyDescriptor[]{ new PropertyDescriptor("avanta" , Ultraman. class), new PropertyDescriptor("name" , Ultraman. class) }; } catch (IntrospectionException e) { e.printStackTrace(); return null ; } } }信息类会先从Bean类所在的包内查找,如上例中搜索路径为com.cwind.introspector.UltramanBeanInfo。搜索路径也可以通过Introspector.setBeanInfoSearchPath()进行设置。使用BeanInfo类是为了获取对bean属性的控制权。只需提供属性名和所属的bean类,就可以为每个属性构建一个PropertyDescriptor。
演示类Superhero及其另一子类Titan定义:
package com.cwind.introspector; public class Superhero { private String name ; private String superPower ; private int age ; public Superhero(){ this.name = "defaultName" ; this.superPower = "defaultSuperPower" ; this.age = 0; } public Superhero(String name, String superPower, int age) { super(); this.name = name; this.superPower = superPower; this.age = age; } public String getName() { return name ; } public void setName(String name) { this.name = name; } public String getSuperPower() { return superPower ; } public void setSuperPower(String superPower) { this.superPower = superPower; } public int getAge() { return age ; } public void setAge(int age) { this.age = age; } } package com.cwind.introspector; public class Titan extends Superhero { private double height ; private double weight ; public Titan(double height, double weight) { super(); this.height = height; this.weight = weight; } public double getHeight() { return height ; } public void setHeight(double height) { this.height = height; } public double getWeight() { return weight ; } public void setWeight(double weight) { this.weight = weight; } }
可以看到,Ultraman类有一个显式的BeanInfo类,其中的属性描述符仅包括"avanta"和继承自父类的"name"。Titan没有显式的BeanInfo类。下面用一个测试类来打印Introspector获取的BeanInfo信息,分别打印两个Ultraman和Titan实例的属性名称及其对应的值,比较其异同。
package com.cwind.introspector; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.InvocationTargetException; public class IntrospectorTest { public static void main(String[] args) throws IntrospectionException, IllegalArgumentException, IllegalAccessException, InvocationTargetException{ PropertyDescriptor[] ultramanProps = Introspector.getBeanInfo(Ultraman.class).getPropertyDescriptors(); Ultraman sailor = new Ultraman("sailor" ); for(PropertyDescriptor prop : ultramanProps){ System. out.println("Property name: " + prop.getName()+ ", value: "+ prop.getReadMethod().invoke(sailor, null)); } System. out.println(); PropertyDescriptor[] titanProps = Introspector.getBeanInfo(Titan.class).getPropertyDescriptors(); Titan titan = new Titan(999,888); for(PropertyDescriptor prop : titanProps){ System. out.println("Property name: " + prop.getName()+ ", value: "+ prop.getReadMethod().invoke(titan, null)); } } }
输出结果如下:
Property name: avanta, value: sailor Property name: name, value: defaultName Property name: age, value: 0 Property name: class, value: class com.cwind.introspector.Titan Property name: height, value: 999.0 Property name: name, value: defaultName Property name: superPower, value: defaultSuperPower Property name: weight, value: 888.0
可以看到,对于前者,只打印出其显式BeanInfo类中返回的属性描述符所对应的属性;对于后者,使用低层次的反射来获取所有属性,并按照属性名称字母序将属性描述符数组返回。
为了更好的性能,Introspector缓存BeanInfo;因此,若在使用多个类加载器的应用程序中使用Introspector须小心谨慎。可以调用Introspector.flushCaches或Introspector.flushFromCaches方法从缓存中清空内省的类。
Reference:
1. Java API 1.6
2. Java反射总结
3. Java内省机制
4. Java语言的反射和内省
6. Java2核心技术 卷II:高级特性,第8章:JavaBean构件;【美】Cay S. Horstmann, Gary Cornell 著;机械工业出版社
相关推荐
"JAVA的内省机制(introspector)与反射机制(reflection)" JAVA 的内省机制(introspector)和反射机制(reflection)是两个重要的概念,在 JAVA 编程中扮演着至关重要的角色。那么,什么是内省机制和反射机制?它们...
Java内省(Introspector)是Java语言提供的一种机制,用于在运行时分析Java对象的属性、方法和事件。...了解并熟练掌握Java内省机制,可以提高代码的灵活性和可维护性,尤其是在处理基于JavaBean的复杂系统时。
`Introspector` 是Java内省的核心类,它提供了一系列的方法来获取关于JavaBean的信息。例如,`Introspector.getBeanInfo(Class)` 方法可以获取指定类的BeanInfo,这包含了关于类的属性(PropertyDescriptor)、事件...
通过内省机制,框架能够将HTTP请求中的表单数据自动映射到Bean的属性上,前提是这些属性具有相应的getter和setter方法。 #### 四、总结 反射和内省都是Java中非常强大的特性,能够显著提高程序的灵活性和可扩展性...
内省(Introspection)则是Java提供的一种用于获取和修改对象属性的能力,主要通过java.beans包中的Introspector和PropertyDescriptor类实现。它主要用于处理JavaBeans规范的对象,可以获取Bean的属性、事件和方法...
在 J2EE 应用中,内省机制常用于框架自动识别 JavaBean 的属性,并根据这些属性进行相应的操作,例如:在容器中自动注入依赖。 ### 总结 JavaBean 作为一种标准的组件模型,在 Java 开发中起着重要作用。它不仅有...
内省机制(Introspection)是Java提供的一种工具,用于获取和操作JavaBeans对象的属性。例如,通过Introspector、BeanInfo和PropertyDescriptor等类,可以方便地获取和设置JavaBean的属性值。 BeanUtils是Apache ...
- **内省**是指Java程序能够访问并处理自身结构的能力。通过`java.beans`包提供的API,可以实现对象状态的查询和修改。 - 例如:使用`Introspector`和`PropertyDescriptor`来获取和设置对象的属性。 ##### 6. 注解...
在Java中,Sun公司提供的内省(Introspection)API,如java.beans.PropertyDescriptor和java.beans.Introspector,虽然强大但确实相对复杂,不便于开发者快速访问和修改Bean的属性。BeanUtils库则通过提供一套更直观...
JavaBeans API提供了一系列的类和接口,如Introspector、PropertyDescriptor、EventSetDescriptor等,用于创建、操作和理解JavaBean的属性、事件和方法。 14.6 JavaBeans的事件处理 事件处理是JavaBeans中的重要...
- 内省:使用Introspector类进行对象属性的获取和设置。 - 注解:理解注解的作用,以及如何自定义注解并配合反射使用。 - 泛型:理解泛型的基本概念,提高代码的类型安全性。 - 代理:学习动态代理和静态代理,...