接上文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. 反编译DLL并修改DLL中的内容

    使用场景:针对当前用户因不愿意进行软件版本升级,但又希望可以解决当前问题,此时可以考虑通过反编辑DLL进行修改内容,然后重新生成新的DLL 操作步骤: 1.首先使用ILSpy.exe反编译DLL,查看 ...

  2. IDEA常见问题和设置

    1.查看方法的文档:快捷键 Ctrl-Q(Ctrl-J(mac)) 2.历史记录 3.IDEA控制台输出中文乱码问题 4.修改Idea默认的maven等全局设置 5.idea 启动时报错javax.i ...

  3. All-in-One Office,不容错过的办公插件

      WPS Office是由金山自主研发的一款办公软件套装,具备办公软件最常用的文字.表格.演示等多种功能. 这款国产办公软件不仅免费,而且具有内存小.海量模板.兼容性强.操作更加符合中国人使用习惯等 ...

  4. Kubernetes1.16下部署Prometheus+node-exporter+Grafana+AlertManager 监控系统

    Prometheus 持久化安装 我们prometheus采用nfs挂载方式来存储数据,同时使用configMap管理配置文件.并且我们将所有的prometheus存储在kube-system #建议 ...

  5. 7、DockerFile案例:自定义centos、自定义tomcat、webapps项目发布

    1.Base镜像(scratch) Docker Hub 中 99% 的镜像都是通过在 base 镜像中安装和配置需要的软件构建出来的 2.自定义镜像mycentos 1.Hub默认CentOS镜像什 ...

  6. mac使用brew安装的PHP替换自带的PHP

    在.zshrc文件后面加上 export PATH="$(brew --prefix homebrew/php/php56)/bin:$PATH"

  7. Django基础之给视图加装饰器

    1. 使用装饰器装饰FBV FBV本身就是一个函数,所以和给普通的函数加装饰器无差: def wrapper(func): def inner(*args, **kwargs): start_time ...

  8. 函数柯里化与偏函数+bind

    简单理解: 1,函数柯里化就是把多参数函数分解为多return的单参数函数: 举个例子(伪代码): function func (a, b, c){ return } 柯里化为 function fu ...

  9. Nginx之搭建反向代理实现tomcat分布式集群

    参考博文: Nginx反向代理实现Tomcat分布式集群 1. jdk 安装 jdk 下载网址: http://www.oracle.com/technetwork/java/javase/downl ...

  10. Nginx-HTTP之ngx_http_top_body_filter

    1. ngx_http_top_body_filter 该链表用于构造响应消息的响应正文. 大致有以下模块在该链表中插入了自己的函数: ngx_http_range_filter_module: ng ...