# JavaBean

  • JavaBean 规范
    1. 类使用 public 修饰
    2. public 修饰的无参构造器
    3. 包含属性的操作方法,即有 public 修饰的 getter/setter 方法
  • boolean 类型或 Boolean 类型的字段以 is 开头时,属性名会去掉前面的 is
  • boolean 类型的字段没有对应的 getter 方法,取而代之是 isXxx 方法,如 isMan
  • JavaBean:符合 JavaBean 规范的 Java 类,是可重复使用组件
  • 成员:属性(property)、方法(method)、事件(event)
  • JavaBean 的属性由 getter/setter 方法所决定,例如某个类有 age 属性,意味着该类包含 setAge() 或 getAge() 方法
  • 通常作为 DTO(数据传输对象),用来封装值对象,在各层之间传递数据

# 内省机制

  • 用于获取和操作 JavaBean 中的成员信息

  • java.beans 包下

# Introspector 类

  • 通过分别分析 bean 的类和父类,寻找显式或隐式信息,使用这些信息构建一个全面描述目标 bean 的 BeanInfo 对象
  • 类方法
    BeanInfo getBeanInfo(Class<?> beanClass):在 JavaBean 上进行内省,获取其所有成员信息(包括继承的)
    BeanInfo getBeanInfo(Class<?> beanClass, Class<?> stopClass):在给定的“断”点之下,在 JavaBean 上进行内省,获取其所有成员信息
    String decapitalize(String name):获得一个字符串并将它转换成普通 Java 变量名称大写形式(通常意味着将首字符从大写转换成小写,但当有多个字符且第一个和第二个字符都是大写字符时,不执行任何操作

# BeanInfo 接口

  • PropertyDescriptor[] getPropertyDescriptors():获取其中的属性描述器
  • MethodDescriptor[] getMethodDescriptors():获取其中的方法描述器

# PropertyDescriptor 类

  • Class<?> getPropertyType():获得属性的类型的 Class 对象
  • String getName():获取此属性名
  • Method getReadMethod():获取属性值的 get 方法
  • Method getWriteMethod():获取属性值的 set 方法
// JavaBean 和 Map 之间的相互转换
public class BeanMapUtils {
    // 把一个 Map 对象转换为一个 JavaBean 对象
    public static <T> T map2bean(Map<String, Object> map, Class<T> beanType) throws Exception {
        T obj = beanType.newInstance();
        BeanInfo beanInfo = Introspector.getBeanInfo(beanType, Object.class);
        PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
        for (PropertyDescriptor pd : pds) {
            Object value = map.get(pd.getName());
            pd.getWriteMethod().invoke(obj, value);
        }    
        return obj;
    }
    
    // 把一个 JavaBean 对象转换为以一个 Map 对象
    public static Map<String, Object> bean2map(Object bean) throws Exception {
        Map<String, Object> map = new HashMap<>();
        BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass(), Object.class);
        PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
        for (PropertyDescriptor pd : pds) {
            String name = pd.getName();
            Object value = pd.getReadMethod().invoke(bean);
            map.put(name, value);
        }
        return map;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# BeansUtils 工具类

  • 需要的 jar 包:commons-beanutils:commons-beanutils
  • 类方法
    String getProperty(Object bean, String name):获取 bean 对象中属性名为 name 的值
    void setProperty(Object bean, String name, Object value):设置 bean 对象中属性名为 name 的值为 value
    void copyProperties(Object dest, Object orig):JavaBean 对象之间属性值的拷贝;或 Map 对象转 JavaBean 对象
    Map<String, String> describe(final Object bean):JavaBean 对象转 Map 对象

# MapStruct (opens new window)

  • JavaBean 映射工具

# Lombok 工具 (opens new window)

  • 通过命令行安装 jar 包,然后在项目中导入 lombok.jar
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>
1
2
3
4
5

# Lombok 中的常用注解

  • val:用在局部变量前,相当于将变量声明为 final

  • @NonNull:在方法参数前增加这个注解会自动在方法内对该参数进行是否为空的校验,如果为空,则抛出 NullPointerException

  • @Cleanup:自动管理资源,用在局部变量前,在当前变量范围内即将执行完毕退出之前会自动清理资源,自动生成 try-finally 这样的代码来关闭资源

  • @Getter、@Setter:用在属性或类上,为属性生成 getter 和 setter 方法

  • @EqualsAndHashCode:生成 equals() 方法 和 hashCode() 方法,在实现 equals 和 hashCode 时,默认使用类型中所有非 static、非 transient 的字段(可以使用 @EqualsAndHashCode.Exclude 排除一些字段),且不考虑父类(callSuper = false)

  • @ToString:实现 toString() 方法,属性:exclude、callSuper

  • @Data:相当于同时使用了 @Getter、@Setter、@ToString、@EqualsAndHashCode、@RequiredArgsConstructor

  • @Value:用在类上,是 @Data 的不可变形式,相当于为属性添加 final 声明,只提供 getter 方法,而不提供 setter 方法

  • @Accessors:用在类、字段上(A more fluent API for getters and setters),属性:fluent、chain、prefix,Widget testWidget = new Widget().id(1).name("foo");

  • @Builder:用在类、构造器、方法上,使用构建器创建对象

    • Widget testWidget = Widget.builder().id(1).name("foo").build();
    • 属性:toBuilder = true,Widget newWidget = testWidget.toBuilder().id(2).build();@Builder.Default(用在字段上,表示使用字段的初始化表达式作为默认值,如果没有该注解,不会设置默认值);setterPrefix = "set"
    • 用在类上时,相当于添加 @AllArgsConstructor(access = AccessLevel.PACKAGE) 到类并将 @Builder 应用到这个全参数构造器,此时没有生成无参数构造器,建议和 @NoArgsConstructor、@AllArgsConstructor 一起使用(此时需注意字段默认值问题)。如果有显式构造器,请将 @Builder 放在构造器而不是类上。
  • @SuperBuilder:使构造器也适用于来自父类的成员变量(要求所有父类也有 @superbuilder)

  • @FieldNameConstants:生成一个内部类型,其中包含每个字段的字段名称的字符串常量;或者,生成一个内部枚举,其中枚举值与每个字段名称匹配

  • @NoArgsConstructor:生成无参数的构造器

  • @AllArgsConstructor

  • @RequiredArgsConstructor:生成带参构造器,参数是类中所有带有 @NonNull 注解的和以 final 修饰的未经初始化的字段,属性:

    • staticName:生成指定名称的静态构造方法(原来的实例构造方法将会被私有)
    • onConstructor:在构造方法的入参上添加注解
    • access:设置构造方法的访问权限
    • force:是否强制对未赋值的 final 字段初始化值
  • @Delegate:用在字段上,生成将调用转发到该字段的委托方法

  • @Synchronized:用在方法上,将方法声明为同步的,并自动加锁,锁对象是一个私有的属性 $lock$LOCK

  • @SneakyThrows (opens new window):自动抛受检异常,而无需显式在方法上使用 throws 语句,try { ... } catch (Throwable t) { throw Lombok.sneakyThrow(t);} 由 Lombok 生成的代码不会忽略、包装、替换或以其它方式修改抛出的已检查异常;它只是伪造了编译器。在 JVM(类文件)级别,无论方法的 throws 子句如何,都可以抛出所有异常,无论是否检查,这就是为什么这样做的原因。(The code generated by lombok will not ignore, wrap, replace, or otherwise modify the thrown checked exception; it simply fakes out the compiler. On the JVM (class file) level, all exceptions, checked or not, can be thrown regardless of the throws clause of your methods, which is why this works.)

  • @With:

  • @Slf4j:为类提供一个 属性名为 log 的 SLF4J 日志对象(推荐)
    private static final Logger log = LoggerFactory.getLogger(Test.class);
    log.error(各类参数或者对象toString() + "_" + e.getMessage(), e);

  • @Log4j2:为类提供一个 属性名为 log 的 Log4j2 日志对象

    @Log4j2 和 @Slf4j 只是日志记录 API,和实际日志记录框架无关

# SLF4J

  • 常见的日志框架:Logback、Log4j、Log4j2、commons-logging、JDK 自带的 java.util.logging 等

SLF4J

SLF4J 实现了三种功能:

  1. 提供了统一的日志门面 API(日志标准),即图中紫色部分,实现了中立的日志记录 API。
  2. 桥接功能,即图中蓝色部分,用来把各种日志框架的 API(图中绿色部分)桥接到 SLF4J API。这样一来,即便程序中使用了各种日志 API 记录日志,最终都可以桥接到 SLF4J 门面 API。
  3. 适配/绑定功能,即图中红色部分,可以实现 SLF4J API 和实际日志框架(图中灰色部分)的绑定。日志框架本身没有实现 SLF4J API,所以需要有一个前置转换。Logback 是按照 SLF4J API 标准实现的,因此不需要绑定模块做转换。

# JBoss Logging

Since version 4.0, Hibernate has used the JBoss Logging library for its logging needs. Like SLF4J and Jakarta’s commons-logging, JBoss Logging is a "logging bridge" providing integration with numerous logging frameworks. JBoss Logging was chosen because of its i18n support and its support for "message ids". This is largely the seminal documentation of JBoss Logging since JBoss Logging currently provides no documentation of its own.

https://docs.jboss.org/hibernate/orm/4.3/topical/html/logging/Logging.html

  • org.jboss.logging.LoggerProviders
Updated at: 2024-04-22 15:04:27