您的位置:首页 > 房产 > 家装 > java反射机制及beanUtils的实现原理

java反射机制及beanUtils的实现原理

2025/4/24 7:08:20 来源:https://blog.csdn.net/m0_72167535/article/details/139421975  浏览:    关键词:java反射机制及beanUtils的实现原理

目录

1.反射机制说明

2.VO,DTO,PO的说明

3.beanUtils的实现原理

4.beanUtils的简单示例


1.反射机制说明

Java的反射机制允许程序在运行时检查和操作类、方法、字段等结构。通过反射,可以动态地创建对象、调用方法、获取/设置字段的值,而无需在编译时确定这些操作。反射的核心类是java.lang.reflect包中的MethodFieldConstructor等。使用反射需要注意性能开销和安全性问题。

获取类的Class对象

Class<?> clazz = MyClass.class;

 实例化对象

MyClass myObject = (MyClass) clazz.getDeclaredConstructor().newInstance();

 获取和调用方法

Method method = clazz.getDeclaredMethod("methodName", parameterTypes);
method.setAccessible(true); // 如果方法是private的,需要设置accessible为true
Object result = method.invoke(myObject, args);

 获取和设置字段值

Field field = clazz.getDeclaredField("fieldName");
field.setAccessible(true); // 如果字段是private的,需要设置accessible为true
Object value = field.get(myObject);
field.set(myObject, newValue);

操作构造函数

Constructor<?> constructor = clazz.getDeclaredConstructor(parameterTypes);
constructor.setAccessible(true); // 如果构造函数是private的,需要设置accessible为true
MyClass myObject = (MyClass) constructor.newInstance(args);

2.VO,DTO,PO的说明

VO(Value Object)值对象

VO就是展示用的数据,不管展示方式是网页,还是客户端,还是APP,只要是这个东西是让人看到的,这就叫VO,这个大家都很理解,反正就是我们的接口返回给前端的对象都是用VO来返回,跟DTO不一样的是,VO是我们返回给前端,DTO是我们从前端接收的时候用的,即一个是入参,一个是返回结果

DTO(Data Transfer Object)数据传输对象

这个传输通常指的前后端之间的传输

DTO是一个比较特殊的对象,他有两种存在形式:

一种是前端和后端交互所使用的对象,另一种是微服务之间的一种传输对象,我们一般也是用DTO来进行传输

PO(Persistant Object)持久对象

PO比较好理解,简单说PO就是数据库中的记录,一个PO的数据结构对应着库中表的结构,表中的一条记录就是一个PO对象,通常PO里面除了get,set之外没有别的方法,对于PO来说,数量是相对固定的,一定不会超过数据库表的数量,等同于BO,这俩概念是一致的

3.beanUtils的实现原理

在后端的各个层中进行数据传输时,经常使用beanUtils进行bean的拷贝,其实现原理就是通过java的放射机制实现。

package org.springframework.beans;private static void copyProperties(Object source, Object target, @Nullable Class<?> editable, @Nullable String... ignoreProperties) throws BeansException {Assert.notNull(source, "Source must not be null");Assert.notNull(target, "Target must not be null");Class<?> actualEditable = target.getClass();if (editable != null) {if (!editable.isInstance(target)) {throw new IllegalArgumentException("Target class [" + target.getClass().getName() + "] not assignable to Editable class [" + editable.getName() + "]");}actualEditable = editable;}PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);List<String> ignoreList = ignoreProperties != null ? Arrays.asList(ignoreProperties) : null;PropertyDescriptor[] var7 = targetPds;int var8 = targetPds.length;for(int var9 = 0; var9 < var8; ++var9) {PropertyDescriptor targetPd = var7[var9];Method writeMethod = targetPd.getWriteMethod();if (writeMethod != null && (ignoreList == null || !ignoreList.contains(targetPd.getName()))) {PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName());if (sourcePd != null) {Method readMethod = sourcePd.getReadMethod();if (readMethod != null) {ResolvableType sourceResolvableType = ResolvableType.forMethodReturnType(readMethod);ResolvableType targetResolvableType = ResolvableType.forMethodParameter(writeMethod, 0);boolean isAssignable = !sourceResolvableType.hasUnresolvableGenerics() && !targetResolvableType.hasUnresolvableGenerics() ? targetResolvableType.isAssignableFrom(sourceResolvableType) : ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType());if (isAssignable) {try {if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {readMethod.setAccessible(true);}Object value = readMethod.invoke(source);if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {writeMethod.setAccessible(true);}writeMethod.invoke(target, value);} catch (Throwable var18) {throw new FatalBeanException("Could not copy property '" + targetPd.getName() + "' from source to target", var18);}}}}}}}

4.beanUtils的简单示例

public class BeanToolUtils {public static void copy(Object source, Object target) throws Exception {Class<?> sourceClass = source.getClass();Class<?> targeteClass = target.getClass();Field[] fields = targeteClass.getDeclaredFields();// 输出字段信息for (Field field : fields) {String name = field.getName();if ("serialVersionUID".equals(name)) {continue;}String getterName = "get" + name.substring(0, 1).toUpperCase() + name.substring(1);String setterName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1);Method getMethod = sourceClass.getMethod(getterName);if(!ObjectUtils.isEmpty(getMethod)){Object val = getMethod.invoke(source);Method setMethod = targeteClass.getMethod(setterName,field.getType());setMethod.invoke(target, val);}}}
}

说明:

获取目标bean的class对象,通过class对象获取目标bean的所有属性,循环属性信息,获取属性的get和set方法,执行来源bean的get方法获取属性值,执行目标bean的set方法,设置属性值,完成bean的赋值操作。

参照:

Java 中的反射机制(两万字超全详解)_java反射-CSDN博客

原来不止有 BeanUtils 啊,来看看更优秀的 MapStruct 吧

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com