很多人内省 与 反射 容易搞乱,反射在上一篇已经介绍了,主要用于用(大)Class 类取(小)class类的成员变量、方法、构造。而内省则是用于利用取来的信息搞些事情。
用于测试的类
public class Stu {
private String name;//姓名 这里声明为公有成员
private int age;//年纪
//1类的构造
//1-1.空构造
public Stu() {
}
//1-2 完整构造
public Stu(String name, int age) {
this.name = name;
this.age = age;
}
//2 成员GET AND SET
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//3.(可选)ToString 方法
@Override
public String toString() {
return "Stu{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
通过Bean方式获取成员
public void test() throws IntrospectionException {
BeanInfo beanInfo= Introspector.getBeanInfo(Stu.class,Object.class);//通过Bean从父类继承的属性
PropertyDescriptor[] pd= beanInfo.getPropertyDescriptors();//取得所有成员
for (PropertyDescriptor p:pd) {
System.out.println(p.getName());//获取成员名称
}
}
通过Bean方式为成员类型、取值、赋值
Stu stu=new Stu();
PropertyDescriptor pd= new
PropertyDescriptor("name",Stu.class);
//获取字段的类型
System.out.println(pd.getPropertyType());
//读取
Method md= pd.getWriteMethod();//写入开关
md.invoke(stu,"张三");//写入
//读取
md=pd.getReadMethod();//读取开关
//读取测试
System.out.println(md.invoke(stu,null));
//----测试2
System.out.println(stu.getName());
典型案例
现在有这么一个需求:数据库配置在一个文件内,通过类加载进去
创建一个类
package com;
public class Config {
private String dbip;
private String dbuser;
private String dbpwd;
public String getDbip() {
return dbip;
}
public void setDbip(String dbip) {
this.dbip = dbip;
}
public String getDbuser() {
return dbuser;
}
public void setDbuser(String dbuser) {
this.dbuser = dbuser;
}
public String getDbpwd() {
return dbpwd;
}
public void setDbpwd(String dbpwd) {
this.dbpwd = dbpwd;
}
public Config() {
}
@Override
public String toString() {
return "Config{" +
"dbip='" + dbip + '\'' +
", dbuser='" + dbuser + '\'' +
", dbpwd='" + dbpwd + '\'' +
'}';
}
}
创建一个配置文件
bean.name=com.Config
bean.dbip=10.11.11.110
bean.dbuser=sa
bean.dbpwd=11
创建一个组装工厂类
package com;
import java.beans.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Properties;
public class BeanFactory {
private static Properties prop=new Properties();//创建一个读取对象
//加载类默认执行方法
static {
InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("com/config.properties");
try {
prop.load(in);//把读取到的流文件加载到读取对象中去
} catch (IOException e) {
e.printStackTrace();
}
}
//创建一个读取对象用于与读取对象发生关系
public static Object getbean(String classname){
Object obj=null;//创建这个Object
String beanname = prop.getProperty(classname);//让读取对象到配置文件中读取关键字相关的类信息
try {
Class<?> aClass = Class.forName(beanname);//装载类信息
obj=aClass.newInstance();//实例化这个类
BeanInfo beanInfo = Introspector.getBeanInfo(aClass);//用Bean的方式读取这个类
PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();//获取类成员数组
for (int i = 0; i < pds.length; i++) {
String mdname = pds[i].getName();//获取成员
if ("dbip".equals(mdname)){
Method md= pds[i].getWriteMethod();//打开写入开关
md.invoke(obj,prop.getProperty("bean.dbip"));//写入
}
if ("dbuser".equals(mdname)){
Method md= pds[i].getWriteMethod();
md.invoke(obj,prop.getProperty("bean.dbuser"));
}
if ("dbpwd".equals(mdname)){
Method md= pds[i].getWriteMethod();
md.invoke(obj,prop.getProperty("bean.dbpwd"));
}
}
} catch (ClassNotFoundException | IntrospectionException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return obj;//返回
}
}
前台调用
Config con=(Config)BeanFactory.getbean("bean.name");
System.out.println(con.toString());
效果
Config{dbip=‘10.11.11.110’, dbuser=‘SA’, dbpwd=‘11’}
这就有点意思了吧,不要急,下期我们接着捋 AOP