内省基本概念
内省(IntroSpector)是Java语言对Bean类属性、事件的一种缺省处理方法。如类A中有属性name,那我们可以通过getName,setName来得到其值或设置新的值。通过getName/setName来访问name属性,这就是默认的规则。
Java中提供了一套API用来访问某个属性的getter/setter方法,通过这些API可以使你不需要了解这个规则,这些API在java.beans中,一般的做法是通过Introspector的getBeanInfo方法来获取某个对象的BeanInfo信息,然后通过BeanIfno来获取属性的描述器(PropertyDescriptor),通过这个属性描述器就可以获取某个属性对应的getter/setter方法,然后就可以通过反制机制来调用这些方法
Introspector 相关 API
- Introspector类
Introspetor类为通过工具学习有关受目标JavaBean支持的属性、事件和方法的知识提供了一个标准方法:
static BeanInfo getBeanInfo(Class<?> beanClass)
在JavaBean上进行内省, 了解其所有属性 ,公开的方法和事件
- BeanInfo类
该类实现此BeanInfo接口并提供有关其bean的方法、属性、事件等显示信息
MethodDescriptor[] getMethodDescriptors()
获得beans MethodDescriptor
PropertyDescriptro[] getPropertyDescriptors()
获得beans PropertyDescriptor
- PropertyDescriptor 类
PropertyDescriptor描述JavaBean通过一对存储器方法导出的一个属性
Method getReadMethod()
获取读取属性的方法
Method getWriteMethod()
获得用于定稿属性值的方法
- MethodDescriptor类
MethodDescriptor描述了一种特殊方法
即JavaBean支持从其它脑袋瓜地其进行外部访问
Method getMethod()
获得此MethodDescriptro封闭的方法
user
package com.laolang.se.fanshe.domain;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 被代理类
*/
public class User {
private static final Logger log = LoggerFactory.getLogger(User.class);
public User() {
log.info("调用无参构造函数");
}
public User(Long id, String name, Integer age) {
log.info("调用带参构造函数");
this.id = id;
this.name = name;
this.age = age;
}
private String say(){
return name;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
private Long id;
private String name;
private Integer age;
}
UserFactory
package com.laolang.se.fanshe;
import com.laolang.se.fanshe.domain.User;
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 UserFactory {
private static Properties config = new Properties();
static {
InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("bean.properties");
// 加载属性文件
try {
config.load(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static User getUser(String name) {
String className = config.getProperty(name);
try {
Class<?> clazz = Class.forName(className);
User user = (User) clazz.newInstance();
// 内省:获取bean信息
BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
// 通过bean信息获取所有属性描述器
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
if("name".equals(propertyDescriptor.getName())){
String userName = config.getProperty("user.name");
Method method = propertyDescriptor.getWriteMethod();
method.invoke(user,userName);
}else if ("age".equals(propertyDescriptor.getName())){
Method method = propertyDescriptor.getWriteMethod();
method.invoke(user,Integer.parseInt(config.getProperty("user.age")));
}else if ( "id".equals(propertyDescriptor.getName())){
Method method = propertyDescriptor.getWriteMethod();
method.invoke(user,Long.parseLong(config.getProperty("user.id")));
}
}
return user;
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IntrospectionException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
}
Main
package com.laolang.se.fanshe;
import com.laolang.se.fanshe.domain.User;
public class Main {
public static void main(String[] args) {
User user = UserFactory.getUser("user");
System.out.println(user);
}
}
bean.properties
# 配置JavaBean信息
user=com.laolang.se.fanshe.domain.User
user.name=小代码
user.age=23
user.id=1