当前位置: 首页 > 后端技术 > Java

BeanInfo

时间:2023-04-02 01:18:43 Java

Java的BeanInfo在工作中用的不多。我在学习spring源码的时候,发现SpringBoot启动的时候,会设置一个属性叫“spring.beaninfo.ignore”,这个只能在网上找。这个配置的意思是是否跳过对javaBeanInfo的查找,没有找到其他信息,但是BeanInfo是什么?JavaBean介绍维基百科对JavaBean的定义:JavaBeans是Java中的一个特殊类,可以将多个对象封装成一个对象(bean)。它的特点是序列化,提供了一个无参数的构造函数,并提供了getter方法和setter方法来访问对象的属性。名称中的“Bean”是Java中可重用软件组件的惯用术语。要成为JavaBean类,您必须遵循有关命名、构造函数和方法的特定规范。有了这些规范,就有了可以使用、重用、替换和连接JavaBeans的工具。规范如下:有一个公共的无参数构造函数。属性可以通过get、set、is(可以用来代替布尔属性上的get)方法或其他遵循特定命名约定的方法访问。可序列化。以下是合法JavaBean的定义:publicclassPersonBeanimplementsjava.io.Serializable{/***name属性(注意大小写)*/privateStringname=null;私人布尔死者=假;/**无参构造Device(无参数)*/publicPersonBean(){}/***name属性的getter方法*/publicStringgetName(){returnname;}/***name属性的Setter方法*@paramvalue*/publicvoidsetName(finalStringvalue){name=value;/***deceased属性的Getter方法*布尔属性的Getter方法的不同形式(这里使用is而不是get)*/publicbooleanisDeceased(){returndeceased;}/***deceased属性的setter方法*@paramvalue*/publicvoidsetDeceased(finalbooleanvalue){deceased=value;}}JavaBeanIntrospection用一个简单的SpringMVC用户登录场景来描述JavaBeanIntrospection,当用户登录时,前端表单传递的参数通常是一个Json字符串如下:{"username":"xxx","password":"xxxx"}后端接受表单的地方,通常可以使用一个带有RequestBody的JavaBean接收参数,形式为:publicvoidlogin(@RequestBodyLoginRequestrequest){//做登录}其中,LoginRequest类似如下格式:publicclassLoginRequest{publicStringgetUsername(){returnusername;}publicvoidsetUsername(Stringusername){this.username=username;}publicStringgetPassword(){返回密码;}publicvoidsetPassword(Stringpassword){this.password=password;}私有字符串用户名;privateStringpassword;}那么前端Json是如何映射到后端LoginRequest中对应的属性呢?可以看到LoginRequest中的字段都是私有类型,不能直接设置字段值(反射可以设置,但不适合),只能通过Setter方法设置,但是程序知道JavaBean有哪些Setter方法?这里使用了JavaBean的自省机制JavaBean自省工具IntrospectorJavabean工具包提供了java自省工具Introspector。本工具可以通过以下方法获取Javabean的自省结果BeanInfo(后面详述),获取BeanInfo的过程如下图//在Object类中停止检索,可以选择在任意父类中停止BeanInfobeanInfo=Introspector.getBeanInfo(JavaBeanDemo.class,Object.class);JavaBean自省结果BeanInfo通过java内省工具Introspector的getBeanInfo方法,我们可以得到一个JavaBean的自省BeanInfo,得到的BeanInfo包含以下属性:Bean类相关信息Bean事件信息Bean属性信息Bean方法信息Bean附加属性信息Componenticon自省结果BeanInfo类型BeanInfo只是一个自省结果接口,这个接口在Java中有三种实现:introspectionresults,JEEdevelopmentintrospection内省结果都是这种类型。另外,Spring自定义了一个内省结果类型ExtendedBeanInfo,主要用于识别返回值不为空的Setter方法。Spring的BeanUtils.copyPropertiesBeanUtils.copyProperties用户在两个对象之间复制属性。底层基于JavaBean的内省机制。通过自省得到复制源对象和目标对象属性的read方法和write方法,然后调用相应的方法。复制属性。下面是BeanUtils.copyProperties的过程。BeanUtils优化了JavaBean自省的一些机制。到目前为止,你有没有发现Java自省的一些缺点呢?BeanUtils并发优化Java自省的结果会缓存在ThreadGroupContext中,通过synchonrized关键字(下图红框)锁定缓存,使得同一线程组的线程无法并行自省。Spring的BeanUtils在Java内省之上添加了另一层缓存。这层缓存是使用ConcurrentHashMap实现的,从而提高了自省的效率。BeanUtilsSetter属性标识优化在Java默认的自省过程中,setter方法的返回值必须为null。如果不为null,则无法识别为有效的JavaBean属性(下图中红色部分),Spring自定义了一个BeanInfoExtendedBeanInfo解决了这个问题。spring.beaninfo.ignore回到原来的spring.beaninfo.ignore,这个配置是用来忽略所有自定义BeanInfo类的搜索。BeanUtils性能测试复制方式1万次复制耗时100万次复制耗时1复制耗时1亿次ModelMapper复制262mills3875mills283177millsBeanUtils复制3mills369mills20347mills直接复制大约为0mills5mills438mills可以看出BeanUtils耗时大约是50倍以上直接复制。publicclassBeanUtilsPerformanceTest{publicstaticvoidmain(String[]args){//预热虚拟机loopBeanUtils(100000);loopCopyByHand(100000);//复制10,000次System.out.println("\n循环10000次:");loopBeanUtils(10000);loopCopyByHand(10000);//复制100万次System.out.println("\nloop1000000次:");loopBeanUtils(1000000);loopCopyByHand(1000000);//复制1亿次的情况System.out.println("\n循环100000000次:");loopBeanUtils(100000000);loopCopyByHand(100000000);}privatestaticvoidloopBeanUtils(intloopTimes){TestBeanDemosource=newTestBeanDemo();target=newTestBeanDemo();长启动=System.currentTimeMillis();for(inti=0;i版权所有,禁止转载!