接上文Java各种反射性能对比

BeanUtils.getProperty的原理其实以下方法类似,但稍有不同

  1. //代码片段4.1

  2.        PropertyDescriptor descriptor=null;

  3.        BeanInfo beanInfo =Introspector.getBeanInfo(SimpleBean.class);
  4.        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
  5.        for(PropertyDescriptor propertyDescriptor : propertyDescriptors){
  6.            if(propertyDescriptor.getName().equals("name")){
  7.                descriptor=propertyDescriptor;
  8.                break;
  9.            }
  10.        }
  11.        for(long i =0; i < times; i++){
  12.            descriptor.getReadMethod().invoke(bean);
  13.        }

先获取BeanInfo,然后获取所有PropertyDescriptors, 通过与想要获取的属性名对比,比如“name”,来获取对应的propertyDescriptor,最后循环getReadMethod和invoke。

上面的测试消耗了大概2800ms( 因为只缓存了对应的PrepertyDescriptor,而不是对应的method ),BeanUtils.getProperty性能仍只有其1/7

最开始是怀疑BeanUtils.getProperty没有对获得的PropertyDescriptor进行缓存,每次都重新查找对一个你的PropertyDescriptor,通过阅读源码,发现其通过一个与当前classloader绑定的ContextClassLoaderLocal实例来缓存匹配到的property,属性valueByClassLoader就是用来保存的。

private Map valueByClassLoader = new WeakHashMap();

这样性能应该和上面的一样才对。

通过JProfiler分析调用过程,

获取PropertyDescriptor[]的调用消耗了2.9%的时间

  1.    publicPropertyDescriptor[] getPropertyDescriptors(Object bean){
  2.        if(bean ==null){
  3.            thrownewIllegalArgumentException("No bean specified");
  4.        }
  5.        return(getPropertyDescriptors(bean.getClass()));
  6.    }

获取property的readMethod消耗了6.4%的时间

  1.    Method getReadMethod(Class clazz,PropertyDescriptor descriptor){
  2.        return(MethodUtils.getAccessibleMethod(clazz, descriptor.getReadMethod()));
  3.    }

而真正的method调用只消耗了1.6%的时间

  1. privateObject invokeMethod(
  2.                        Method method,
  3.                        Object bean,
  4.                        Object[] values)
  5.                            throws
  6.                                IllegalAccessException,
  7.                                InvocationTargetException{
  8.        if(bean ==null){
  9.            thrownewIllegalArgumentException("No bean specified "+
  10.                "- this should have been checked before reaching this method");
  11.        }
  12.        try{
  13.            
  14.            return method.invoke(bean, values);
  15.        
  16.        }catch(NullPointerException cause){
  17.              ....省略
  18. }

这些和反射有关的调用其实都没有花太多时间,3000ms×(1.6%+6.4%)=2400ms,和代码片段4.1中的2800ms基本相同.

请看以下的方法调用时间:

这些方法占了整个调用过程的54%的时间,这些是为了使BeanUtils.getProperty不仅仅能够获取bean的一级属性,还能够判断我们所传入的属性是否是嵌套属性,是否是从数组取值或者是map中取值,需要对传入的属性名不断的解析,调用String.length()和String.charAt()两个方法进行循环判断。

感觉大部分情况下,我们都只是解析一级属性,BeanUtils中提供了一个方法,getSimpleProperty,测试的时间并没有比getProperty快多少,1亿次调用时间为15299ms,主要时间和上面一样花在了传入的property name的解析和验证上。

BeanUtils.getProperty性能分析的更多相关文章

  1. MyBatisPlus性能分析插件,条件构造器,代码自动生成器详解

    性能分析插件 我们在平时的开发中,会遇到一些慢sql,测试,druid MP(MyBatisPlus)也提供性能分析插件,如果超过这个时间就停止 不过官方在3.2版本的时候取消了,原因如下 条件构造器 ...

  2. 如何进行python性能分析?

    在分析python代码性能瓶颈,但又不想修改源代码的时候,ipython shell以及第三方库提供了很多扩展工具,可以不用在代码里面加上统计性能的装饰器,也能很方便直观的分析代码性能.下面以我自己实 ...

  3. SQL Server-聚焦IN VS EXISTS VS JOIN性能分析(十九)

    前言 本节我们开始讲讲这一系列性能比较的终极篇IN VS EXISTS VS JOIN的性能分析,前面系列有人一直在说场景不够,这里我们结合查询索引列.非索引列.查询小表.查询大表来综合分析,简短的内 ...

  4. SQL Server-聚焦NOT IN VS NOT EXISTS VS LEFT JOIN...IS NULL性能分析(十八)

    前言 本节我们来综合比较NOT IN VS NOT EXISTS VS LEFT JOIN...IS NULL的性能,简短的内容,深入的理解,Always to review the basics. ...

  5. SQL Server-聚焦LEFT JOIN...IS NULL AND NOT EXISTS性能分析(十七)

    前言 本节我们来分析LEFT JOIN和NOT EXISTS,简短的内容,深入的理解,Always to review the basics. LEFT JOIN...IS NULL和NOT EXIS ...

  6. SQL Server-聚焦EXISTS AND IN性能分析(十六)

    前言 前面我们学习了NOT EXISTS和NOT IN的比较,当然少不了EXISTS和IN的比较,所以本节我们来学习EXISTS和IN的比较,简短的内容,深入的理解,Always to review ...

  7. SQL Server-聚焦NOT EXISTS AND NOT IN性能分析(十五)

    前言 上一节我们分析了INNER JOIN和IN,对于不同场景其性能是不一样的,本节我们接着分析NOT EXISTS和NOT IN,简短的内容,深入的理解,Always to review the b ...

  8. SQL Server-聚焦INNER JOIN AND IN性能分析(十四)

    前言 本节我们来讲讲联接综合知识,我们在大多教程或理论书上都在讲用哪好,哪个性能不如哪个的性能,但是真正讲到问题的实质却不是太多,所以才有了本系列每一篇的篇幅不是太多,但是肯定是我用心去查找许多资料而 ...

  9. Java 性能分析工具 , 第 3 部分: Java Mission Control

    引言 本文为 Java 性能分析工具系列文章第三篇,这里将介绍如何使用 Java 任务控制器 Java Mission Control 深入分析 Java 应用程序的性能,为程序开发人员在使用 Jav ...

随机推荐

  1. zabbix上添加交换机监控记事

    ​ zabbix上添加交换机监控记事 ​ 第一次使用zabbix来添加监控华为s5720交换机,根本找不到头绪,像个无头的苍蝇一样的百度来处理,结果都没有任何效果,给自己增加了很多痛苦和心烦,增加不少 ...

  2. 对List<Map>里的map的某个属性重复的值进行处理的方法

    package test; import java.util.*;import java.util.stream.Collectors; public class Test5 { public sta ...

  3. spark_rdd 一波怼完面试官系列

    Resilient Distributed dataset , 弹性分布式数据集. 分布式内存的抽象使用,实现了以操作本地集合的方式来操作分布式数据集的抽象实现. RDD是Spark最核心的东西,它表 ...

  4. 【Winform-最大化窗体】Winform设置窗体最大化,填满整个屏幕

    设置窗体最大化,填满整个屏幕//this.MaximizedBounds = Screen.PrimaryScreen.WorkingArea;//this.MaximumSize = Screen. ...

  5. Mysql数据库多对多关系未建新表

    原则上,多对多关系是要新建一个关系表的,当遇到没有新建表的情况下如何查询多对多的SQL呢? FIND_IN_SET(str,strlist) 官网:http://dev.mysql.com/doc/r ...

  6. MFC 用户登录、注册、工作主窗体

    创建项目由向导生成的窗体作为工作的主窗体.用户登录.注册窗体添加对话框来实现. [具体功能] 1.主窗体应该出现在登录窗体成功之后. 2.登录窗体关闭(右上角❌),程序直接退出. 在App.cpp的I ...

  7. Ubuntu操作及Linux基础知识

    part 1: Ubuntu操作基础 1.调整字体的大小 调大:crtl+shift+“+”  调小:crtl+“-” 2.不要把虚拟机全屏的时候截屏,要不然会认为是Linux系统截屏而非Window ...

  8. pe头

    1.dos头 结构: struct _IMAGE_DOS_HEADER {     WORD e_magic;     WORD e_cblp;     WORD e_cp;     WORD e_c ...

  9. Enable file editing in Visual Studio's debug mode

    Visual Studio 使用及调试必知必会 http://www.cnblogs.com/luminji/p/3287728.html How do I enable file editing i ...

  10. 小米oj 重拍数组求最大和

     重排数组求最大和 序号:#34难度:困难时间限制:1000ms内存限制:10M 描述 假设有一个n元素的数组(数组的元素索引从1开始),针对这个数组有q个查询请求,每个请求由一对整数li,ri组成, ...