当前位置: 代码网 > it编程>编程语言>Java > java反射机制及beanUtils的实现原理分析

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

2024年12月11日 Java 我要评论
1.反射机制说明java的反射机制允许程序在运行时检查和操作类、方法、字段等结构。通过反射,可以动态地创建对象、调用方法、获取/设置字段的值,而无需在编译时确定这些操作。反射的核心类是java.lan

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的赋值操作。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com