ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

只知道java反射,宁知道内省吗?

2021-05-04 09:52:00  阅读:217  来源: 互联网

标签:java name 内省 知道 public JavaBean UserInfo


1. 前言

上一文中我们封装了一个Mybatis通用 Mapper。为了获得实体类属性我使用了反射。大多数同学也第一感觉会用反射实现,其实还有一种技术也能实现,这就是内省(Introspector)。

2. 什么是内省

在计算机科学中,内省是指计算机程序在运行时(Runtime)检查对象(Object)类型的一种能力,通常也可以称作运行时类型检查。不应该将内省和反射混淆。相对于内省,反射更进一步,是指计算机程序在运行时(Runtime)可以访问、检测和修改它本身状态或行为的一种能力。

Java中的内省是对JavaBean属性、的一种缺省处理方法。看了概念是不是有点懵逼,我也一样。所以我们写个例子来看看就知道了。写之前还要搞清楚JavaBean的定义;

  • 属性是私有的。

  • 有无参的public构造方法。

  • 对于这些属性有公开的getter/setter方法。

但是如果有的类比较“调皮” ,有getter/setter没有对应的实体,也容易被内省到,但是会抛出异常。所以遵守规约是一个有利于我们使用内省。

其实 add/removeis 也认为是操作JavaBean属性的方法,所以我们要小心。

3. Java 内省操作

JavaBean一般用来传递数据使用,我们数据库实体类就是一种典型的JavaBean

public class UserInfo implements Serializable {

    private static final long serialVersionUID = -8938650956516110149L;
    private Long userId;
    private String name;
    private Integer age;
    private String time;

    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

请注意我特意没有给time属性设置getter/setter。接下来我就开始演示使用内省来操作实体了。

Java中通过java.beans.Introspector来进行内省操作。常用的内省操作主要有下面这些,当然还有其它的附加类型

Java 内省

3.1 BeanInfo

BeanInfo就是内省对 JavaBean 的一个整体描述。这里我只想获取UserInfo的描述信息,所以应该这么写:

BeanInfo beanInfo = Introspector.getBeanInfo(UserInfo.class,Object.class);

你可以通过 stop 、flag 两个属性来控制内省分析的深度。

3.2 BeanDescriptor

然后我们看看BeanDescriptor主要有什么:

BeanDescriptor beanDescriptor = beanInfo.getBeanDescriptor();
// cn.felord.kono.entity.UserInfo.class
Class<?> beanClass = beanDescriptor.getBeanClass();
// UserInfo
String name = beanDescriptor.getName();

原来是JavaBeanClass类型和名称。

3.3 PropertyDescriptors

PropertyDescriptor是描述JavaBean的成员属性的,我们打印来看看

Stream.of(beanInfo.getPropertyDescriptors())
        .forEach(System.out::println);
java.beans.PropertyDescriptor[name=age; propertyType=class java.lang.Integer; readMethod=public java.lang.Integer cn.felord.kono.entity.UserInfo.getAge(); writeMethod=public void cn.felord.kono.entity.UserInfo.setAge(java.lang.Integer)]
java.beans.PropertyDescriptor[name=name; propertyType=class java.lang.String; readMethod=public java.lang.String cn.felord.kono.entity.UserInfo.getName(); writeMethod=public void cn.felord.kono.entity.UserInfo.setName(java.lang.String)]
java.beans.PropertyDescriptor[name=userId; propertyType=class java.lang.Long; readMethod=public java.lang.Long cn.felord.kono.entity.UserInfo.getUserId(); writeMethod=public void cn.felord.kono.entity.UserInfo.setUserId(java.lang.Long)]

原来PropertyDescriptor包含了成员属性的名称类型读的方法写的方法。注意到没有居然不包含time属性,因为它没有getter/setter被忽略了。

3.4 MethodDescriptors

顾名思义,一定是描述JavaBean的方法的。这里放出一条打印结果。

java.beans.MethodDescriptor[name=foo; method=public static void cn.felord.kono.entity.UserInfo.foo(java.lang.String)]

包含了方法名称和方法对象(Method)。注意这里混进来了奇怪的方法 foo,是的!我随便写了一个方法。MethodDescriptors 可以包含JavaBean下所有的方法,包括静态方法。当然受到内省深度的制约。

3.5 EventSetDescriptors

目前打印为空,JavaBean 事件发布订阅相关的一些范式,目前我还不知道什么作用。

4. 总结

Java反射是在运行时获取一个类的所有信息,可以操纵类的字段、方法、构造器等,功能非常强大。而内省其实就是反射的一个子集,基于反射实现。专门操作JavaBean的,只关注于JavaBean的属性、方法、事件的一些属性。了解了这个我觉得有必要把通用Mapper重构一下了。


标签:java,name,内省,知道,public,JavaBean,UserInfo
来源: https://blog.51cto.com/u_15127607/2752195

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有