JAVA基础 内省机制

原创 2016年08月31日 06:31:28

注:本文主要记录自 兄弟连_马剑威 JavaSE第三季 第49讲 内省机制

1、JavaBean的概念

  • 什么是JavaBean?
  • Bean理解为组件的意思,JavaBean就是Java组件,在广泛的理解就是一个类,对于组件来说,关键在于要具有“能够被IDE构建工具侦测其属性和事件”的能力,通常在Java中
一个JavaBean要具备这样的命名规则:
  1. 对于一个名称为xxx的属性,通常你要写两个方法:getXxx() 和 setXxx() .任何浏览这些方法的工具,都会把get或set后面的第一个字母自动转换为小写。
  2. 对于布尔型属性,可以使用以上get和set方式,不过也可以把get替换成is
  3. Bean的普通方法不必遵循以上命名规则,不过他们必须是public的
  4. 对于事件,要使用Swing中处理监听器的方式。如addWindowListener,removeWindowListener
2、内省的基本概念
  • 内省(IntroSpector)是Java语言对Bean类属性、事件的一种缺省处理方法。例如类A中有属性name,那我们可以通过getName,setName来得到其值或者设置新的值。
  • 通过getName/setName来访问name属性,这就是默认的规则。
  • Java中提供了一套API用来访问某个属性的getter/setter方法,通过这些API可以使你不需要理解这个规则,这些API存放于包java.beans中,一般的做法是通过类Introspector的getBeanInfo方法来获取某个对象的BeanInfo信息,然后通过BeanInfo来获取属性的描述器(PropertyDescriptor),通过这个属性描述器就可以获取某个属性对应的getter/setter方法,然后我们就可以通过反射机制来调用这些方法。

3、IntroSpector相关API
1、Introspector类:
Introspector类为通过工具学习有关受目标JavaBean支持的属性、事件和方法的知识提供了一个标准方法。
static BeanInfo getBeanInfo(Class<?> beanClass)
在JavaBean上进行反省,了解其所有属性、公开的方法和事件

2、BeanInfo类
该类实现此BeanInfo接口并提供有关其bean的方法、属性、事件等显式信息。
MethodDescriptor[] getMethodDescriptors()
获得 beans MethodDescriptor
PropertyDescriptor[] getPropertyDescriptors()
获得beans PropertyDescriptors

3、PropertyDescriptor类:
PropertyDescriptor描述JavaBean通过一对存储器方法导出的一个属性
Method getReadMethod()
获得应该用于读取属性值的方法
Method getWriteMethod()
获得应该用于写入属性值的方法 

4、MethodDescriptor类:
MethodDescriptor 描述了一种特殊方法
即Java Bean支持从其他组件对其进行外部访问
Method getMethod()
获得此MethodDescriptor封装的方法

实例:
/**
 * javaBean
 *
 */
public class Dog {
	private int age;
	private String name;

	public int getAge() {
		return age;
	}

	public String getName() {
		return name;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public void setName(String name) {
		this.name = name;
	}

}

/**
 * 内省
 *
 */
public class IntroSpectorDemo {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
//		Dog dog=new Dog();//使用者与被使用者耦合
		//不耦合可以使用工厂模式
		Dog dog=DogFactory.getDog("dog");
		
	}

}

/**
 * 工厂类
 *
 */
public class DogFactory {
	public static Dog getDog(String dogname) {
		if("dog".equals(dogname)){
			return  new Dog();//此处也耦合
		}
		return null;
	}
}

但在如上的工厂类里,仍是会用到  new Dog();产生耦合
所以需要采取另外的途径,
如在反射中的:Class.forName("class的全路径")

创建配置文件 bean.properties,使用配置文件的目的是修改方便,相比定义在类中的静态参数而言,当某天代码参数发生变化时,只要修改配置文件中的参数,重启系统即可。而在代码中的参数修改则需要重新修改源码,编译,替换。【注:配置文件如果要正常显示中文,需要将配置文件的编码格式更改为:utf-8】
<pre name="code" class="java">#配置javaBean的全名
dog=IntroSpectorDemo.Dog
dog.name=小白
dog.age=4

在工厂类中通过读取配置文件信息,并利用内省机制生成Dog实例
/**
 * 工厂类
 * @author zhan414
 *
 */
public class DogFactory {
	
	private static Properties config=new Properties();//处理properties文件的工具类,负责读写属性文件
	static{
		//读取属性文件
		InputStream inputStream=Thread.currentThread().getContextClassLoader().getResourceAsStream("bean.properties");
		//加载属性文件
		try {
			config.load(inputStream);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
	public static Dog getDog(String dogname){
		//从Properties对象中根据key获取value
		String className =config.getProperty("dog");
		try {
			//根据类全名获取类信息对象Class对象
			Class dogClass = Class.forName(className);
			//实例化对象
			Dog dog=(Dog) dogClass.newInstance();
			//内省:获取bean信息
			BeanInfo beanInfo=Introspector.getBeanInfo(dogClass);
			//通过bean信息获取所有属性描述器,数组
			PropertyDescriptor[] pds=beanInfo.getPropertyDescriptors();
			//循环遍历属性描述器
			for (PropertyDescriptor propertyDescriptor : pds) {
				if ("name".equals(propertyDescriptor.getName())) {//判断是否是name属性
					String nameValue=config.getProperty("dog.name");
					//通过属性描述器获取该属性的写操作(set方法)
					Method method=propertyDescriptor.getWriteMethod();
					//在dog对象上调用方法
					method.invoke(dog, nameValue);
				}else if ("age".equals(propertyDescriptor.getName())) {
					String  ageValue=config.getProperty("dog.age");
					Method method=propertyDescriptor.getWriteMethod();//内省
					method.invoke(dog, Integer.valueOf(ageValue));
				}
				//返回对某属性的method对象,相比反射要方便许多
				//eg:Method setNameMethod=personClass4.getMethod("setName", String.class);  
			    //	 setNameMethod.invoke(p5, "小花");//相当于 p5.setName("小花");  
			}
			return dog;
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IntrospectionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
}
测试:
public class IntroSpectorDemo {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Dog dog=DogFactory.getDog("dog");
		System.out.println("dog.name= "+dog.getName()+" , dog.age= "+dog.getAge());
	}
}
输出:
dog.name= 小白 , dog.age= 4
可以看到name为乱码,这是因为配置文件中 dog.name的值为中文,未转成 unicode格式
解决方法:修改DogFactory中的properties文件输入静态块,配置输入流的编码格式,如下:
	static {
		try {
			// 读取属性文件
			InputStream inputStream = Thread.currentThread()
					.getContextClassLoader()
					.getResourceAsStream("bean.properties");
			BufferedReader bf = new BufferedReader(new InputStreamReader(
					inputStream, "utf-8"));
			// 加载属性文件
			config.load(bf);
			//关闭流
			inputStream.close();
			bf.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
修改后便可输出中文







eclipse properties文件中文格式使用配置:




版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

Java基础知识—虚拟机类加载机制

1.虚拟机类加载机制定义 虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是Java虚拟机的类加载机制。 2.类的生...

JAVA基础--垃圾回收机制及算法

一、垃圾回收机制的作用 主要有两个作用:   1、跟踪并监控每个Java对象,当某个对象处于不可达状态时,回收该对象所占用的内存。 2、清理内存分配、回收过程中产生的内存碎片。 ...

黑马程序员——java基础笔记:反射机制

——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-一:反射机制的概念 反射,从字面来理解,就是反着来,我们正常的习惯是通过对象来调用属性和方法,反射机制给我们提供了...

javaSE_8系列博客——重要的基础Java类——Excavations(异常处理机制)--2--什么是异常?

术语Excavation是短语“exceptional event”的缩写。定义:一个异常是在执行程序期间发生的一个事件,它破坏程序指令的正常流程。 当方法中发生错误时,该方法将创建一个对象并将其移交...

Java基础---异常处理机制

java.lang.Throwable |java.lang.Error |java.lang.Exception  异常         异常是Java中的重要机...

Java反射基础机制简介

一、什么是反射?Java反射机制是指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称...

黑马程序员——Java基础——多线程的同步、死锁和等待唤醒机制

在线程中,有时候会出现安全问题,就是一个线程的代码还没执行完,CPU就把执行权分配给了其他线程,导致数据出现错误。这些问题我们应该怎么解决呢? 我们可以用到同步来解决。它能让一个线程执行完,在执行过...
  • twa42
  • twa42
  • 2015年06月14日 21:55
  • 122

java反射机制基础示例

package wang.dylan.demo.reflect;import java.lang.reflect.Array; import java.lang.reflect.Constructor...

java中的反射机制(基础篇)

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:JAVA基础 内省机制
举报原因:
原因补充:

(最多只允许输入30个字)