package com.nobody;
import java.beans.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.UUID;
/**
-
@Description
-
@Author Mr.nobody
-
@Date 2021/3/23
-
@Version 1.0.0
*/
public class Demo {
public static void main(String[] args)
throws IntrospectionException, InvocationTargetException, IllegalAccessException {
// 不内省父类的信息,第二个参数stopClass代表从stopClass开始往上的父类不再内省
BeanInfo beanInfo = Introspector.getBeanInfo(Person.class, Object.class);
Person person = new Person(UUID.randomUUID().toString(), “Mr_nobody”, 18);
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
Class<?> propertyType = propertyDescriptor.getPropertyType();
String propertyName = propertyDescriptor.getName();
Method readMethod = propertyDescriptor.getReadMethod();
Method writeMethod = propertyDescriptor.getWriteMethod();
System.out.println(“属性名:” + propertyName);
System.out.println(“属性类型:” + propertyType);
System.out.println(“写方法名:” + writeMethod.getName());
System.out.println(“读方法名:” + readMethod.getName());
if (“age”.equals(propertyName)) {
writeMethod.invoke(person, 20);
}
System.out.println(“属性值:” + readMethod.invoke(person));
System.out.println(“------------------------------------------”);
}
}
}
输出结果:
属性名:age
属性类型:int
写方法名:setAge
读方法名:getAge
属性值:20
属性名:id
属性类型:class java.lang.String
写方法名:setId
读方法名:getId
属性值:a6ccda55-c895-438e-893f-7fa448aba35a
属性名:name
属性类型:class java.lang.String
写方法名:setName
读方法名:getName
属性值:Mr_nobody
当然,除了从BeanInfo对象获取PropertyDescriptor对象,也可以直接new的方式获取。
PropertyDescriptor namePropertyDescriptor = new PropertyDescriptor(“name”, Person.class);
===========================================================================
java.beans.MethodDescriptor,即方法描述器,通过它可以获取到类相关的方法,如下所示:
package com.nobody;
import java.beans.*;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
/**
-
@Description
-
@Author Mr.nobody
-
@Date 2021/3/23
-
@Version 1.0.0
*/
public class Demo {
public static void main(String[] args) throws IntrospectionException {
// 不内省父类的信息,第二个参数stopClass代表从stopClass开始往上的父类不再内省
BeanInfo beanInfo = Introspector.getBeanInfo(Person.class, Object.class);
MethodDescriptor[] methodDescriptors = beanInfo.getMethodDescriptors();
for (MethodDescriptor methodDescriptor : methodDescriptors) {
Method method = methodDescriptor.getMethod();
System.out.println(method);
System.out.println(“方法名:” + method.getName());
Type[] genericParameterTypes = method.getGenericParameterTypes();
if (genericParameterTypes != null) {
for (Type genericParameterType : genericParameterTypes) {
System.out.println(“方法参数类型:” + genericParameterType.getTypeName());
}
}
Class<?> returnType = method.getReturnType();
System.out.println(“方法返回类型:” + returnType.getTypeName());
System.out.println(“---------------------------”);
}
}
}
输出结果如下:
public java.lang.String com.nobody.Person.getName()
方法名:getName
方法返回类型:java.lang.String
public void com.nobody.Person.setId(java.lang.String)
方法名:setId
方法参数类型:java.lang.String
方法返回类型:void
public void com.nobody.Person.setAge(int)
方法名:setAge
方法参数类型:int
方法返回类型:void
public void com.nobody.Person.setName(java.lang.String)
方法名:setName
方法参数类型:java.lang.String
方法返回类型:void
public int com.nobody.Person.getAge()
方法名:getAge
方法返回类型:int
public java.lang.String com.nobody.Person.getId()
方法名:getId
方法返回类型:java.lang.String
public java.lang.String com.nobody.Person.toString()
方法名:toString
方法返回类型:java.lang.String
===============================================================
在项目实战中,我们一般使用最多的是 Introspector
,BeanInfo
,PropertyDescriptor
,这三者结合起来使用。
比如,我们通过内省可以实现,JavaBean和Map互转,不同JavaBean对象属性拷贝等功能。
package com.nobody.util;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
/**
-
@Description Bean工具类
-
@Author Mr.nobody
-
@Date 2021/3/23
-
@Version 1.0.0
*/
public class BeanUtils {
public static Map<String, Object> beanToMap(T bean, boolean putIfNull)
throws IntrospectionException, InvocationTargetException, IllegalAccessException {
if (bean == null) {
return new HashMap<>();
}
Map<String, Object> returnMap = new HashMap<>();
// 获取bean的BeanInfo对象
BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass(), Object.class);
// 获取属性描述器
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
// 属性名
String propertyName = propertyDescriptor.getName();
// 获取该属性的值
Method readMethod = propertyDescriptor.getReadMethod();
// 属性的值
Object value = readMethod.invoke(bean);
if (value == null && !putIfNull) {
continue;
}
returnMap.put(propertyName, value);
}
return returnMap;
}
public static List<Map<String, Object>> beansToMaps(List beans, boolean putIfNull)
throws IllegalAccessException, IntrospectionException, InvocationTargetException {
if (null == beans || beans.size() == 0) {
return new ArrayList<>();
}
List<Map<String, Object>> result = new ArrayList<>(beans.size() + 1);
// 转换每一个bean
for (Object bean : beans) {
result.add(beanToMap(bean, putIfNull));
}
return result;
}
public static T mapToBean(Map<String, Object> map, Class clz)
throws IllegalAccessException, InstantiationException, IntrospectionException,
InvocationTargetException {
// 生成bean实例
T bean = clz.newInstance();
if (null == map) {
return bean;
}
BeanInfo beanInfo = Introspector.getBeanInfo(clz, Object.class);
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
// 属性名
String propertyName = propertyDescriptor.getName();
// 获取属性值
Object value = map.get(propertyName);
// 写入属性值
Method writeMethod = propertyDescriptor.getWriteMethod();
writeMethod.invoke(bean, value);
}
return bean;
}
public static List mapsToBeans(List<Map<String, Object>> maps, Class clz)
throws InvocationTargetException, IntrospectionException, InstantiationException,
IllegalAccessException {
if (null == maps || maps.size() == 0) {
return new ArrayList<>();
}
List result = new ArrayList<>();
for (Map<String, Object> map : maps) {
result.add(mapToBean(map, clz));
}
return result;
}
public static <T1, T2> void copyProperties(T1 origin, T2 dest, boolean setNull,
String[] excludeFieldNames)
throws IntrospectionException, InvocationTargetException, IllegalAccessException {
// 获取源类的BeanInfo对象
BeanInfo originBeanInfo = Introspector.getBeanInfo(origin.getClass(), Object.class);
// 获取源类的属性描述器
PropertyDescriptor[] originPropertyDescriptors = originBeanInfo.getPropertyDescriptors();
// 获取目标类的BeanInfo对象
BeanInfo destBeanInfo = Introspector.getBeanInfo(dest.getClass(), Object.class);
// 获取目标类的属性描述器
PropertyDescriptor[] destPropertyDescriptors = destBeanInfo.getPropertyDescriptors();
for (PropertyDescriptor propertyDescriptor : destPropertyDescriptors) {
String propertyName = propertyDescriptor.getName();
// 是否需要排除的属性
boolean excludeField = false;
if (excludeFieldNames != null) {
for (String excludeFieldName : excludeFieldNames) {
if (Objects.equals(excludeFieldName, propertyName)) {
excludeField = true;
break;
}
}
}
if (excludeField) {
continue;
}
// 遍历源类的所有属性,如果存在此属性则进行拷贝
for (PropertyDescriptor originPropertyDescriptor : originPropertyDescriptors) {
String originPropertyName = originPropertyDescriptor.getName();
if (Objects.equals(propertyName, originPropertyName)) {
// 读取属性值
Method readMethod = originPropertyDescriptor.getReadMethod();
Object srcValue = readMethod.invoke(origin);
if (srcValue != null || setNull) {
// 设置属性值
Method writeMethod = propertyDescriptor.getWriteMethod();
writeMethod.invoke(dest, srcValue);
}
break;
}
}
}
}
public static <T1, T2> void copyProperties(T1 origin, T2 dest)
throws IllegalAccessException, IntrospectionException, InvocationTargetException {
copyProperties(origin, dest, false, null);
}
}
以上是我们手写的JavaBean相关的转换工具类,当然市场上已经有很多成熟的工具包了,例如Apache的commons-beanutils包,里面就提供了许多实际开发中的应用场景会用到的API,大家不妨可以试用看看。
===============================================================
开头提到JavaBean的get/set方法名要遵循某种规则,即驼峰规则。如下,我们将某个属性的get方法换个名字,例如将id属性的get方法名改为getUid()。那么我们就获取不到属性id的读方法的,即取到的是null。因为在取得id这个属性的属性描述器时,我们获取到了属性名,但是因为get方法没有遵循规则,所以调用getReadMethod()
获取不到方法,所以出现空指针。
最后
这份清华大牛整理的进大厂必备的redis视频、面试题和技术文档
祝大家早日进入大厂,拿到满意的薪资和职级~~~加油!!
感谢大家的支持!!
ils包,里面就提供了许多实际开发中的应用场景会用到的API,大家不妨可以试用看看。
===============================================================
开头提到JavaBean的get/set方法名要遵循某种规则,即驼峰规则。如下,我们将某个属性的get方法换个名字,例如将id属性的get方法名改为getUid()。那么我们就获取不到属性id的读方法的,即取到的是null。因为在取得id这个属性的属性描述器时,我们获取到了属性名,但是因为get方法没有遵循规则,所以调用getReadMethod()
获取不到方法,所以出现空指针。
最后
这份清华大牛整理的进大厂必备的redis视频、面试题和技术文档
祝大家早日进入大厂,拿到满意的薪资和职级~~~加油!!
感谢大家的支持!!
[外链图片转存中…(img-sMoYAYky-1720099621798)]