内省的类和方法
Java提供了API用来访问某个属性的getter/setter方法:
Introspector类的getBeanInfo方法获取某个对象的BeanInfo信息;
通过BeanInfo来获取属性的描述器PropertyDescriptor
1、Introspector类:
Introspector.getBeanInfo(Class<?> beanClass)
2、BeanInfo类:
PropertyDescriptor[] getPropertyDescriptors() 获得 beans PropertyDescriptor
MethodDescriptor[] getMethodDescripors() 获得beans MethodDescriptor
3、PropertyDescriptor类:
Method getReadMethod() 获得用于读取属性值的方法(即get方法)
Method getWriteMethod() 获得用于写入属性值的方法(即set方法)
4、MethodDescriptor类:
Method getMethod() 获得此MethodDescriptor封装的方法
Config.properties
bean.name=com.vince.Introspector.Config
bean.username=admin
bean.password=12345
bean.url=https://www.baidu.com
Config.java
package com.vince.Introspector;
public class Config {
private String username;
private String password;
private String url;
public Config() {
}
public Config(String username, String password, String url) {
this.username = username;
this.password = password;
this.url = url;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
@Override
public String toString() {
return "Confog{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
", url='" + url + '\'' +
'}';
}
}
BeanFectory.java
package com.vince.Introspector;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
public class BeanFectory {
private static Properties p = new Properties(); //p是配置文件的对象,为什么要用静态,因为如下配置文件输入流是放在了静态代码块里的
//使用静态代码块读取配置文件:保证配置属性在类被加载的时候只读取一次,避免重复读取
static {
InputStream resourceAsStream = //即读取配置文件生成输入流
Thread.currentThread().getContextClassLoader().getResourceAsStream("com/vince/Introspector/Config.properties"); //这里路径是配置文件的完整路径
try {
p.load(resourceAsStream); //静态代码块中只能是调用静态的属性的方法;将配置文件的输入流加载到配置文件的对象p中(即配置文件里的所有信息就可以获取到了)
} catch (IOException e) {
e.printStackTrace();
}
}
//创建JavaBean的类{即调用配置文件里的具体属性值,创建一个具体的Config的类对象}
public static Object createBean(String name){ //因为配置文件对象是静态的属性,所以这里方法也必须是静态的
Object bean=null;
String beanName = p.getProperty(name); //这里的name是配置文件里的包完整路径的配置名称:bean.name=com.vince.Introspector.Config 的 "bean.name",继而可由bean.name获取它的value
//即通过配置文件里的key(name的值),得到对应key的值
try {
Class<?> aClass = Class.forName(beanName); //可由包的完整路径通过反射获取Class类的对象信息
bean=aClass.newInstance(); //通过Class类对象,获取原目标类的对象
BeanInfo beanInfo = Introspector.getBeanInfo(aClass); //通过内省(Introspector),用反射的Class类信息获取javaBean的描述信息
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); //通过内省(beanInfo),用javaBean的描述信息获取源目标类的所有属性信息
int len = propertyDescriptors.length;
for (int i = 0; i < len; i++) {
String propertyName = propertyDescriptors[i].getName(); //propertyDescriptors[i].getName(),遍历源目标类的所有属性的名称
Method writeMethod = propertyDescriptors[i].getWriteMethod(); //遍历获取源目标类所有属性的set方法
if("username".equals(propertyName)){
writeMethod.invoke(bean, p.getProperty("bean.username")); //相当于调用类属性的set方法,为属性设置具体的值,这里是把配置文件里的key对应的value具体值设置给该属性
}else if("password".equals(propertyName)){
writeMethod.invoke(bean, p.getProperty("bean.password"));
}else if("url".equals(propertyName)){
writeMethod.invoke(bean, p.getProperty("bean.url"));
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IntrospectionException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
return bean;
}
}
BeanTest.java
package com.vince.Introspector;
import org.junit.Test;
public class BeanTest {
@Test
public void getbeantest(){
//因为createBean是一个静态属性方法,所以呢,就不用创建对象的方式调用,可用:类名.方法名 直接调用
//BeanFectory bf = new BeanFectory();
//Object bean = bf.createBean("bean.name");
Config bean = (Config)BeanFectory.createBean("bean.name");
System.out.println(bean.toString());
/**
* 为什么要这么复杂的获取一个对象呢?
* 为了提高代码的可维护性,对于属性值,以后只需更改配置文件即可实现创建一个新的对象
*/
}
}