当前位置: 首页 > news >正文

佛山网站建设推广服务惠州做学校网站

佛山网站建设推广服务,惠州做学校网站,黑龙江网站备案管理局,wordpress远程自动下载图片在实际的项目开发中#xff0c;对象间赋值普遍存在#xff0c;随着双十一、秒杀等电商过程愈加复杂#xff0c;数据量也在不断攀升#xff0c;效率问题#xff0c;浮出水面。 问#xff1a;如果是你来写对象间赋值的代码#xff0c;你会怎么做#xff1f; 答#xf…在实际的项目开发中对象间赋值普遍存在随着双十一、秒杀等电商过程愈加复杂数据量也在不断攀升效率问题浮出水面。 问如果是你来写对象间赋值的代码你会怎么做 答想都不用想直接代码走起来get、set即可。 问下图这样 答对啊你怎么能把我的代码放到网上 问没我只是举个例子 答这涉及到商业机密是很严重的问题 问我发现你挺能扯皮啊直接回答问题行吗 答OKOK我也觉得这样写很low上次这么写之后差点挨打 对象太多ctrl c strl v键盘差点没敲坏而且很容易出错一不留神属性没对应上赋错值了代码看起来很傻缺一个类好几千行全是get、set复制还起个了自以为很优雅的名字transfer如果属性名不能见名知意还得加上每个属性的含义注释基本这种赋值操作都是要加的注释很重要注释很重要注释很重要代码维护起来很麻烦如果对象过多会产生类爆炸问题如果属性过多会严重违背阿里巴巴代码规约一个方法的实际代码最多20行 问行了行了说说怎么解决吧。 答很简单啊可以通过工具类Beanutils直接赋值啊 问我听说工具类最近很卷你用的哪个啊 答就Apache自带的那个啊贼简单。我手写一个给你欣赏一下。 问你这代码报错啊避免用Apache Beanutils进行属性的copy。 答没报错只是严重警告而已代码能跑就行有问题再优化呗 问你这什么态度人事在哪划拉的人为啥会出现严重警告 答拿多少钱干多少活我又不是XXX应该是性能问题吧 问具体什么原因导致的呢 答3000块钱还得手撕一下 apache copyProperties的源代码呗 通过单例模式调用copyProperties但是每一个方法对应一个BeanUtilsBean.getInstance()实例每一个类实例对应一个实例这不算一个真正的单例模式。 public static void copyProperties(Object dest, Object orig) throws IllegalAccessException, InvocationTargetException {BeanUtilsBean.getInstance().copyProperties(dest, orig); }性能瓶颈 -- 日志太多也是病 通过源码可以看到每一个copyProperties都要进行多次类型检查还要打印日志。 /*** org.apache.commons.beanutils.BeanUtils.copyProperties方法源码解析* author 哪吒编程* time 2023-01-07*/ public void copyProperties(Object dest, Object orig) throws IllegalAccessException, InvocationTargetException {// 类型检查if (dest null) {throw new IllegalArgumentException(No destination bean specified);} else if (orig null) {throw new IllegalArgumentException(No origin bean specified);} else {// 打印日志if (this.log.isDebugEnabled()) {this.log.debug(BeanUtils.copyProperties( dest , orig ));}int var5;int var6;String name;Object value;// 类型检查// DanyBean 提供了可以动态修改实现他的类的属性名称、属性值、属性类型的功能if (orig instanceof DynaBean) {// 获取源对象所有属性DynaProperty[] origDescriptors ((DynaBean)orig).getDynaClass().getDynaProperties();DynaProperty[] var4 origDescriptors;var5 origDescriptors.length;for(var6 0; var6 var5; var6) {DynaProperty origDescriptor var4[var6];// 获取源对象属性名name origDescriptor.getName();// 判断源对象是否可读、判断目标对象是否可写if (this.getPropertyUtils().isReadable(orig, name) this.getPropertyUtils().isWriteable(dest, name)) {// 获取对应的值value ((DynaBean)orig).get(name);// 每个属性都调用一次copyPropertythis.copyProperty(dest, name, value);}}} else if (orig instanceof Map) {MapString, Object propMap (Map)orig;Iterator var13 propMap.entrySet().iterator();while(var13.hasNext()) {Map.EntryString, Object entry (Map.Entry)var13.next();String name (String)entry.getKey();if (this.getPropertyUtils().isWriteable(dest, name)) {this.copyProperty(dest, name, entry.getValue());}}} else {PropertyDescriptor[] origDescriptors this.getPropertyUtils().getPropertyDescriptors(orig);PropertyDescriptor[] var14 origDescriptors;var5 origDescriptors.length;for(var6 0; var6 var5; var6) {PropertyDescriptor origDescriptor var14[var6];name origDescriptor.getName();if (!class.equals(name) this.getPropertyUtils().isReadable(orig, name) this.getPropertyUtils().isWriteable(dest, name)) {try {value this.getPropertyUtils().getSimpleProperty(orig, name);this.copyProperty(dest, name, value);} catch (NoSuchMethodException var10) {}}}}} }通过 jvisualvm.exe 检测代码性能 再通过jvisualvm.exe检测一下运行情况果然logging.log4j赫然在列稳居耗时Top1。 问还有其它好的方式吗性能好一点的 答当然有据我了解有 4 种工具类实际上可能会有更多话不多说先简单介绍一下。 org.apache.commons.beanutils.BeanUtils;org.apache.commons.beanutils.PropertyUtils;org.springframework.cglib.beans.BeanCopier;org.springframework.beans.BeanUtils 问那你怎么不用 答OK我来演示一下 package com.nezha.copy;import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.beanutils.PropertyUtils; import org.springframework.cglib.beans.BeanCopier; import org.springframework.util.StopWatch;public class Test {public static void main(String[] args) {User user new User();user.setUserId(1);user.setUserName(哪吒编程);user.setCardId(123);user.setCreateTime(2023-01-03);user.setEmail(666666666qq.com);user.setOperate(哪吒);user.setOrgId(46987916);user.setPassword(123456);user.setPhone(10086);user.setRemark(456);user.setSex(1);user.setStatus(1);user.setTel(110);user.setType(0);user.setUpdateTime(2023-01-05);User target new User();int sum 10000000;apacheBeanUtilsCopyTest(user,target,sum);commonsPropertyCopyTest(user,target,sum);cglibBeanCopyTest(user,target,sum);springBeanCopyTest(user,target,sum);}private static void apacheBeanUtilsCopyTest(User source, User target, int sum) {StopWatch stopWatch new StopWatch();stopWatch.start();for (int i 0; i sum; i) {apacheBeanUtilsCopy(source,target);}stopWatch.stop();System.out.println(使用org.apache.commons.beanutils.BeanUtils方式赋值sum个user对象耗时stopWatch.getLastTaskTimeMillis()毫秒);}/*** org.apache.commons.beanutils.BeanUtils方式*/private static void apacheBeanUtilsCopy(User source, User target) {try {BeanUtils.copyProperties(source, target);} catch (Exception e) {}}private static void commonsPropertyCopyTest(User source, User target, int sum) {StopWatch stopWatch new StopWatch();stopWatch.start();for (int i 0; i sum; i) {commonsPropertyCopy(source,target);}stopWatch.stop();System.out.println(使用org.apache.commons.beanutils.PropertyUtils方式赋值sum个user对象耗时stopWatch.getLastTaskTimeMillis()毫秒);}/*** org.apache.commons.beanutils.PropertyUtils方式*/private static void commonsPropertyCopy(User source, User target) {try {PropertyUtils.copyProperties(target, source);} catch (Exception e) {}}private static void cglibBeanCopyTest(User source, User target, int sum) {StopWatch stopWatch new StopWatch();stopWatch.start();for (int i 0; i sum; i) {cglibBeanCopy(source,target);}stopWatch.stop();System.out.println(使用org.springframework.cglib.beans.BeanCopier方式赋值sum个user对象耗时stopWatch.getLastTaskTimeMillis()毫秒);}/*** org.springframework.cglib.beans.BeanCopier方式*/static BeanCopier copier BeanCopier.create(User.class, User.class, false);private static void cglibBeanCopy(User source, User target) {copier.copy(source, target, null);}private static void springBeanCopyTest(User source, User target, int sum) {StopWatch stopWatch new StopWatch();stopWatch.start();for (int i 0; i sum; i) {springBeanCopy(source,target);}stopWatch.stop();System.out.println(使用org.springframework.beans.BeanUtils.copyProperties方式赋值sum个user对象耗时stopWatch.getLastTaskTimeMillis()毫秒);}/*** org.springframework.beans.BeanUtils.copyProperties方式*/private static void springBeanCopy(User source, User target) {org.springframework.beans.BeanUtils.copyProperties(source, target);} }“四大金刚” 性能统计 方法1000100001000001000000apache BeanUtils906毫秒807毫秒1892毫秒11049毫秒apache PropertyUtils17毫秒96毫秒648毫秒5896毫秒spring cglib BeanCopier0毫秒1毫秒3毫秒10毫秒spring copyProperties87毫秒90毫秒123毫秒482毫秒 不测不知道一测吓一跳差的还真的多。 spring cglib BeanCopier性能最好apache BeanUtils性能最差。 性能走势 -- spring cglib BeanCopier优于 spring copyProperties优于 apache PropertyUtils优于 apache BeanUtils 避免用Apache Beanutils进行属性的copy的问题 上面分析完了下面再看看其它的方法做了哪些优化。 Apache PropertyUtils 源码分析 从源码可以清晰的看到类型检查变成了非空校验去掉了每一次copy的日志记录性能肯定更好了。 类型检查变成了非空校验去掉了每一次copy的日志记录实际赋值的地方由copyProperty变成了DanyBean setSimpleProperty DanyBean 提供了可以动态修改实现他的类的属性名称、属性值、属性类型的功能。 /*** org.apache.commons.beanutils.PropertyUtils方式源码解析* author 哪吒编程* time 2023-01-07*/ public void copyProperties(Object dest, Object orig) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {// 判断数据源和目标对象不是nullif (dest null) {throw new IllegalArgumentException(No destination bean specified);} else if (orig null) {throw new IllegalArgumentException(No origin bean specified);} else {// 删除了org.apache.commons.beanutils.BeanUtils.copyProperties中最为耗时的log日志记录int var5;int var6;String name;Object value;// 类型检查if (orig instanceof DynaBean) {// 获取源对象所有属性DynaProperty[] origDescriptors ((DynaBean)orig).getDynaClass().getDynaProperties();DynaProperty[] var4 origDescriptors;var5 origDescriptors.length;for(var6 0; var6 var5; var6) {DynaProperty origDescriptor var4[var6];// 获取源对象属性名name origDescriptor.getName();// 判断源对象是否可读、判断目标对象是否可写if (this.isReadable(orig, name) this.isWriteable(dest, name)) {try {// 获取对应的值value ((DynaBean)orig).get(name);// 相对于org.apache.commons.beanutils.BeanUtils.copyProperties此处有优化// DanyBean 提供了可以动态修改实现他的类的属性名称、属性值、属性类型的功能if (dest instanceof DynaBean) {((DynaBean)dest).set(name, value);} else {// 每个属性都调用一次copyPropertythis.setSimpleProperty(dest, name, value);}} catch (NoSuchMethodException var12) {if (this.log.isDebugEnabled()) {this.log.debug(Error writing to name on class dest.getClass() , var12);}}}}} else if (orig instanceof Map) {Iterator entries ((Map)orig).entrySet().iterator();while(true) {Map.Entry entry;String name;do {if (!entries.hasNext()) {return;}entry (Map.Entry)entries.next();name (String)entry.getKey();} while(!this.isWriteable(dest, name));try {if (dest instanceof DynaBean) {((DynaBean)dest).set(name, entry.getValue());} else {this.setSimpleProperty(dest, name, entry.getValue());}} catch (NoSuchMethodException var11) {if (this.log.isDebugEnabled()) {this.log.debug(Error writing to name on class dest.getClass() , var11);}}}} else {PropertyDescriptor[] origDescriptors this.getPropertyDescriptors(orig);PropertyDescriptor[] var16 origDescriptors;var5 origDescriptors.length;for(var6 0; var6 var5; var6) {PropertyDescriptor origDescriptor var16[var6];name origDescriptor.getName();if (this.isReadable(orig, name) this.isWriteable(dest, name)) {try {value this.getSimpleProperty(orig, name);if (dest instanceof DynaBean) {((DynaBean)dest).set(name, value);} else {this.setSimpleProperty(dest, name, value);}} catch (NoSuchMethodException var10) {if (this.log.isDebugEnabled()) {this.log.debug(Error writing to name on class dest.getClass() , var10);}}}}}} }通过 jvisualvm.exe 检测代码性能 再通过jvisualvm.exe检测一下运行情况果然logging.log4j没有了其他的基本不变。 Spring copyProperties 源码分析 判断数据源和目标对象的非空判断改为了断言每次copy没有日志记录没有if (orig instanceof DynaBean) {这个类型检查增加了放开权限的步骤 /*** org.springframework.beans.BeanUtils.copyProperties方法源码解析* author 哪吒编程* time 2023-01-07*/ private static void copyProperties(Object source, Object target, Nullable Class? editable,Nullable String... ignoreProperties) throws BeansException {// 判断数据源和目标对象不是nullAssert.notNull(source, Source must not be null);Assert.notNull(target, Target must not be null);/*** 若target设置了泛型则默认使用泛型* 若是 editable 是 null则此处忽略* 一般情况下editable都默认为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;}// 获取target中全部的属性描述PropertyDescriptor[] targetPds getPropertyDescriptors(actualEditable);// 需要忽略的属性ListString ignoreList (ignoreProperties ! null ? Arrays.asList(ignoreProperties) : null);for (PropertyDescriptor targetPd : targetPds) {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();/*** 源对象存在读取方法、数据是可复制的* writeMethod.getParameterTypes()[0]获取 writeMethod 的第一个入参类型* readMethod.getReturnType()获取 readMethod 的返回值类型* 判断返回值类型和入参类型是否存在继承关系只有是继承关系或相等的情况下才会进行注入*/if (readMethod ! null ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType())) {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 ex) {throw new FatalBeanException(Could not copy property targetPd.getName() from source to target, ex);}}}}} }总结 阿里的友情提示避免用Apache Beanutils进行对象的copy还是很有道理的。 Apache Beanutils的性能问题出现在类型校验和每一次copy的日志记录 Apache PropertyUtils 进行了如下优化 类型检查变成了非空校验去掉了每一次copy的日志记录实际赋值的地方由copyProperty变成了DanyBean setSimpleProperty Spring copyProperties 进行了如下优化 判断数据源和目标对象的非空判断改为了断言每次copy没有日志记录没有if (orig instanceof DynaBean) {这个类型检查增加了放开权限的步骤 Java学习路线总结搬砖工逆袭Java架构师 10万字208道Java经典面试题总结(附答案) Java基础教程系列 Java基础教程系列进阶篇
http://www.dnsts.com.cn/news/49406.html

相关文章:

  • 做我女朋友网站网站外包公司该如何运营
  • 企业网站建设的步骤过程动画设计师招聘
  • 免费 空间 网站 国外中国建设银行登录官网
  • 益阳建设公司网站东莞人才市场招聘
  • 哪个网站做译员好建设网站哪家公司比较好
  • 沧州青县网站建设wordpress 速度慢
  • 四川省建设主管部门网站推荐做流程图的网站
  • 如何查询网站点击率wordpress完美商城
  • 怎样建英文网站做网站数据库有哪些
  • 鼓楼徐州网站开发网站规划 时间
  • 电商网站建设的目的跟意义连云港建网站公司
  • 做网站的难点是什么大学生创新创业大赛ppt
  • 个人自助网站店铺装修设计网站
  • 那个网站可以做空比特币移动互联网营销公司
  • 南山企业网站建设如何做贴吧类网站多钱
  • 南阳做个网站多少钱廊坊app网站制作
  • 怎么把安装的字体导入wordpress济南网站优化费用
  • 织梦 网站名称南昌房产网官方
  • 济南专业网站制作最近文章 wordpress
  • 网站选项卡图标网络营销就是建立企业网站
  • 龙华建设网站公司网站的宽度
  • 利用access数据库做网站葫芦岛市营商环境建设管理局网站
  • 个人网站要备案嘛锦绣大地seo
  • 那些网站企业可以免费展示手机优化大师怎么卸载
  • 做网站需要什么样的服务器有做美食的视频网站么
  • 如何发布一个自己的网站服务器怎么做网站教程
  • 自建站需要注册公司吗美食杰网站的建设目的
  • 彩票网站做一级代理犯法吗网站后台管理系统制作教程
  • 网站开始怎么做电子商务网站建设课后习题
  • 深圳做网站哪家便宜深圳知名企业