纯净、安全、绿色的下载网站

首页|软件分类|下载排行|最新软件|IT学院

当前位置:首页IT学院IT技术

Java中的BeanInfo 有关Java中的BeanInfo介绍

御狐神   2021-09-10 我要评论
想了解有关Java中的BeanInfo介绍的相关内容吗御狐神在本文为您仔细讲解Java中的BeanInfo的相关知识和一些Code实例欢迎阅读和指正我们先划重点:Java中的BeanInfo,Java,BeanInfo下面大家一起来学习吧

1、JavaBean介绍

维基百科JavaBean的定义:JavaBeans是Java中一种特殊的类可以将多个对象封装到一个对象(bean)中特点是可序列化提供无参构造器提供getter方法和setter方法访问对象的属性名称中的“Bean”是用于Java的可重用软件组件的惯用叫法要成为JavaBean类则必需遵循关于命名、构造器、方法的特定规范有了这些规范才能有可以使用、复用、替代和连接JavaBeans的工具规范如下:

  • 有一个public的无参数构造器
  • 属性可以通过getsetis(可以替代get用在布尔型属性上)方法或遵循特定命名规范的其他方法访问
  • 可序列化

以下为一个合法的JavaBean的定义:

public class PersonBean implements java.io.Serializable {

    /**
     * name 属性(注意大小寫)
     */
    private String name = null;

    private boolean deceased = false;

    /** 无参构造器(没有参数) */
    public PersonBean() {
    }

    /**
     * name 属性的Getter方法
     */
    public String getName() {
        return name;
    }

    /**
     * name 属性的Setter方法
     * @param value
     */
    public void setName(final String value) {
        name = value;
    }

    /**
     * deceased 属性的Getter方法
     * 布尔型属性的Getter方法的不同形式(这里使用了is而非get)
     */
    public boolean isDeceased() {
        return deceased;
    }

    /**
     * deceased 属性的Setter方法
     * @param value
     */
    public void setDeceased(final boolean value) {
        deceased = value;
    }
}

2、JavaBean的自省

用一个简单的SpringMVC用户登录的场景来描述一下JavaBean的自省用户登录时候前端表单传递的参数通常是一个如下Json字符串:

{
 "username":"xxx",
 "password":"xxxx"
}


后端接受表单的地方通常可以使用一个JavaBeanRequestBody的形式接收参数:

public void login(@RequestBody LoginRequest request){
     // Do login
}


其中LoginRequest类似于如下的格式:

public class LoginRequest {
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    private String username;
    private String password;
}

那么前端的Json如何映射到后端LoginRequest中的对应属性之上呢?可以看到LoginRequest中的字段都是private类型无法直接设置字段值(反射虽然可以设置但是并不合适)只能通过Setter方法进行设置但是程序怎么知道JavaBean有哪些Setter方法呢?此处就用到了JavaBean的内省机制

3、JavaBean内省工具Introspector

Java bean的工具包中提供了java内省工具Introspector该工具可以通过以下方法获取Java bean 的内省结果BeanInfo(后文详细介绍)获取BeanInfo的流程如下图所示

// 在Object类时候停止检索可以选择在任意一个父类停止
BeanInfo beanInfo = Introspector.getBeanInfo(JavaBeanDemo.class,Object.class);

4、JavaBean内省结果BeanInfo

通过java的内省工具IntrospectorgetBeanInfo方法我们可以获取一个JavaBean的内省BeanInfo获取到的BeanInfo包含以下属性:

  • Bean的类相关信息
  • Bean的事件信息
  • Bean的属性信息
  • Bean的方法信息
  • 额外属性信息
  • Component的图标

5、内省结果BeanInfo的类型

BeanInfo只是一个内省结果的接口Java中对该接口的实现有以下三种

  • ApplicationBeanInfo:Apple desktop相关的JavaBean内省结果
  • ComponentBeanInfo:Java Awt组件的内省结果如按钮等
  • GenericBeanInfo:通用的内省结果JEE开发中的内省结果都为该类型

此外Spring自定义了一个内省结果类型叫ExtendedBeanInfo主要用于识别返回值不为空的Setter方法

6、Spring的BeanUtils.copyProperties

BeanUtils.copyProperties用户在两个对象之间进行属性的复制底层基于JavaBean的内省机制通过内省得到拷贝源对象和目的对象属性的读方法和写方法然后调用对应的方法进行属性的复制以下为BeanUtils.copyProperties的流程

BeanUtilsJavaBean内省的一些机制进行优化到这里大家有没有发现Java内省的一些缺点呢?

7、BeanUtils并发问题优化

Java内省的结果会缓存在ThreadGroupContext中并且通过synchonrized关键字对缓存加锁(下图中的红框部分)导致同一个线程组中的线程无法并行内省

SpringBeanUtils在Java内省之上又添加了一层缓存这层缓存使用ConcurrentHashMap实现从而提高了内省的效率

8、BeanUtils Setter属性识别优化

在Java默认的内省过程中setter方法的返回值必须是null如果不是null的话无法识别为有效的JavaBean属性(下图中的红色部分),Spring 自定义了一个BeanInfo ExtendedBeanInfo解决了这个问题

回到最初提到的spring.beaninfo.ignore这个配置用来忽略所有自定义的BeanInfo类的搜索.

9、BeanUtils 性能测试

可以看出:BeanUtils花费的时间约为直接复制的50倍以上

public class BeanUtilsPerformanceTest {

    public static void main(String[] args){
        // 预热虚拟机
        loopBeanUtils(100000);
        loopCopyByHand(100000);

        // 复制1万次的情况
        System.out.println("\nloop 10000 times:");
        loopBeanUtils(10000);
        loopCopyByHand(10000);

        // 复制1百万次的情况
        System.out.println("\nloop 1000000 times:");
        loopBeanUtils(1000000);
        loopCopyByHand(1000000);

        // 复制1亿次的情况
        System.out.println("\nloop 100000000 times:");
        loopBeanUtils(100000000);
        loopCopyByHand(100000000);
    }

    private static void loopBeanUtils(int loopTimes){
        TestBeanDemo source = new TestBeanDemo();
        TestBeanDemo target = new TestBeanDemo();
        long start = System.currentTimeMillis();
        for (int i=0;i<loopTimes;i++){
            BeanUtils.copyProperties(source,target);
        }
        System.out.println("BeanUtils cost times:"+String.valueOf(System.currentTimeMillis()-start));
    }

    private static void loopCopyByHand(int loopTimes){
        TestBeanDemo source = new TestBeanDemo();
        TestBeanDemo target = new TestBeanDemo();
        long start = System.currentTimeMillis();
        for (int i=0;i<loopTimes;i++){
            target.setField1(source.getField1());
            target.setField2(source.getField2());
            target.setField3(source.getField3());
            target.setField4(source.getField4());
            target.setField5(source.getField5());
        }
        System.out.println("Copy field one by one times:"+String.valueOf(System.currentTimeMillis()-start));
    }

    @Data
    private static class TestBeanDemo{
        private String field1 = UUID.randomUUID().toString();
        private String field2 = UUID.randomUUID().toString();
        private String field3 = UUID.randomUUID().toString();
        private String field4 = UUID.randomUUID().toString();
        private String field5 = UUID.randomUUID().toString();

    }
}

相关文章

猜您喜欢

网友评论

Copyright 2020 www.sopisoft.net 【绿软下载站】 版权所有 软件发布

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 点此查看联系方式