接上文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. Visual Studio中使用GitHub

    一.简介 GitHub被微软收购后免费开放了私人仓库,这对个人或小型团队来说简直是福音.GitHub高效免费,无论是团队代码管理还是DevOps都不再话下,特别是对于想要开放研究成果提高知名度的团队或 ...

  2. 使用Barrier分三步将大象放入冰箱

    class Program { //构造大象和冰箱 private static ElephantsAndFridges elephantsAndFridges = new ElephantsAndF ...

  3. TensorFlow中numpy与tensor数据相互转化

    numpy与tensor数据相互转化: *Numpy2Tensor 虽然TensorFlow网络在输入Numpy数据时会自动转换为Tensor来处理,但是我们自己也可以去显式的转换: data_ten ...

  4. [zhuanzai]Bean对象注入失败 .NoSuchBeanDefinitionException: No qualifying bean of type..

    nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying b ...

  5. rac 关于RACScheduler的一点学习

    RACScheduler  信号调度器,是一个线性执行队列,rac中的信号可以在RACScheduler上执行任务.发送结果,底层用GCD封装的. rac中提供生成线程的几个方法: 1:schedul ...

  6. BZOJ3032 七夕祭[中位数]

    发现是一个类似于“纸牌均分”的问题.然后发现,只要列数整除目标.行数整除目标就一定可以. 如果只移动列,并不会影响行,也就是同一行不会多不会少.只移动行同理. 所以可以把两个问题分开来看,处理起来互不 ...

  7. Java中wait()与notify()理解

    通常,多线程之间需要协调工作.例如,浏览器的一个显示图片的线程displayThread想要执行显示图片的任务,必须等待下载线程 downloadThread将该图片下载完毕.如果图片还没有下载完,d ...

  8. kudu_cm_web安装

    [root@Node2 opt]# echo never > /sys/kernel/mm/transparent_hugepage/defrag[root@Node2 opt]# echo n ...

  9. 用node.js读写文件

    node.js没有二进制数据类型,却提供了类似字节数组的“流“数据类型,着一种数据类型在文件系统模块中频频出现 node.js打开文件 fs = require('fs'); console.log( ...

  10. BZOJ 1027: [JSOI2007]合金 (计算几何+Floyd求最小环)

    题解就看这位仁兄的吧-不过代码还是别看他的了- 同样的方法-我200ms,他2000ms. 常数的幽怨- CODE #include <bits/stdc++.h> using names ...