Java中JavaBean对象和Map的互相转换

浅浅的花香味﹌ 2024-04-01 16:49 151阅读 0赞

Java中JavaBean对象和Map的互相转换

  • 1.JavaBean转Map
    • 1.1.简介
    • 1.2.反射知识
    • 1.3.简单转换
      1. 4.属性里面套属性转换
      1. 5.总结
  • 2.Map转JavaBean对象
    • 2.1.简介
    • 2.2.Introspector介绍
    • 2.3.BeanInfo介绍
    • 2.4用反射实现转换
    • 2.5.利用Introspector(内省)的方式转换

1.JavaBean转Map

1.1.简介

这篇博客是通过反射进行实现转换的

在学习redis中,发现了一个知识点,就是Java对象转map,视频中的内容是通过hutool工具转换的,但是我们学习者肯定不能只通过工具来进行转换,更多的是通过这个知识点学习到他的底层是如何进行转换的。

1.2.反射知识

  1. // 新建一个对象
  2. UserDTO userDTO = new UserDTO(1L,"zhangsan","123");
  3. // 通过reflect获取所有属性
  4. // userDTO.getClass().getDeclaredFields() // 暴力获取所有的属性字段
  5. for (Field field : userDTO.getClass().getDeclaredFields()) {
  6. // 设置暴力反射,获取私有属性
  7. field.setAccessible(true);
  8. try {
  9. /**
  10. field.getName() 获取属性字段的字段名称
  11. field.get(userDTO) 相当于 userDTO.getField();
  12. */
  13. map.put(field.getName(),field.get(userDTO));
  14. } catch (IllegalAccessException e) {
  15. e.printStackTrace();
  16. }
  17. }
  18. for (String s : map.keySet()) {
  19. System.out.println(s+"=="+map.get(s));
  20. }

1.3.简单转换

  1. @Test
  2. void contextLoads() {
  3. Map<String, Object> map = new HashMap<>();
  4. UserDTO userDTO = new UserDTO(1L,"zhangsan","123");
  5. // 通过reflect获取所有属性
  6. for (Field field : userDTO.getClass().getDeclaredFields()) {
  7. // 设置暴力反射,获取私有属性
  8. field.setAccessible(true);
  9. try {
  10. map.put(field.getName(),field.get(userDTO));
  11. } catch (IllegalAccessException e) {
  12. e.printStackTrace();
  13. }
  14. }
  15. for (String s : map.keySet()) {
  16. System.out.println(s+"=="+map.get(s));
  17. }
  18. }

1. 4.属性里面套属性转换

实体类

  1. package com.sky;
  2. import com.sky.dto.UserDTO;
  3. import lombok.AllArgsConstructor;
  4. import lombok.Data;
  5. import lombok.NoArgsConstructor;
  6. import java.util.List;
  7. /**
  8. * @author 尹稳健~
  9. * @version 1.0
  10. * @time 2022/11/9
  11. */
  12. @Data
  13. @AllArgsConstructor
  14. @NoArgsConstructor
  15. public class Clazz {
  16. private String ClazzName;
  17. @OneSelf
  18. List<UserDTO> userDTOList;
  19. }

自定义注解

  1. package com.sky;
  2. import java.lang.annotation.Retention;
  3. import java.lang.annotation.RetentionPolicy;
  4. /**
  5. * @author 尹稳健~
  6. * @version 1.0
  7. * @time 2022/11/9
  8. */
  9. @Retention(RetentionPolicy.RUNTIME)
  10. public @interface OneSelf {
  11. }

转换方法:

  1. public Map<String,Object> beanToMap(Object o){
  2. Map<String, Object> map = new HashMap<>();
  3. // 通过reflect获取所有树形
  4. for (Field field : o.getClass().getDeclaredFields()) {
  5. // 设置暴力反射,获取私有属性
  6. field.setAccessible(true);
  7. try {
  8. if (field.get(o) != null){
  9. Class<?> aClass = field.get(o).getClass();
  10. OneSelf annotation = aClass.getAnnotation(OneSelf.class);
  11. if (annotation!=null){
  12. Map<String, Object> beanToMap = beanToMap(field.get(o));
  13. map.put(field.getName(),beanToMap);
  14. }else{
  15. map.put(field.getName(),field.get(o));
  16. }
  17. }
  18. } catch (IllegalAccessException e) {
  19. e.printStackTrace();
  20. }
  21. }
  22. return map;
  23. }

1. 5.总结

  • 就是通过自定义注解来判断是否需要递归转换
  • 嵌套的话,应该还有其他方法可以研究一下

2.Map转JavaBean对象

2.1.简介

在实际项目中相信大多数人都使用过工具类,比如说commons下的和hutool工具类,但是我们只是知道如何调用这个API,而不知道他方法的底层是通过什么样的思路进行实现的。
通过对一些底层的了解和学习,能学到更多的知识,了解底层的一些实现方式,拓展自己的思维。
我将从下面开始介绍如何将JavaBean对象转换为Map。

2.2.Introspector介绍

Introspector是JDK中java.beans包下的类,它为目标JavaBean提供了一种了解原类方法、属性和事件的标准方法。通俗的说,就是可以通过Introspector构建一个BeanInfo对象,而这个BeanInfo对象中包含了目标类中的属性、方法和事件的描述信息,然后可以使用这个BeanInfo对象对目标对象进行相关操作。

JDK原文:

  • Introspector类提供了一种标准的工具来了解目标Java Bean支持的属性,事件和方法。
  • 对于这三种信息中的每一种,Introspector将分别分析bean的类和超类,寻找显式或隐式信息,并使用该信息构建一个全面描述目标bean的BeanInfo对象。
  • 对于每个类“Foo”,如果存在相应的“FooBeanInfo”类,在查询信息时提供非空值,则显式信息可能可用。 我们首先通过获取目标bean类的完整的包限定名称并附加“BeanInfo”来形成一个新的类名称来查找BeanInfo类。 如果失败,那么我们将使用该名称的最终类名组件,并在BeanInfo包搜索路径中指定的每个包中查找该类。

方法介绍:


































































修饰符 返回类型 方法名称和参数 描述
static String decapitalize(String name) 实用方法来取一个字符串并将其转换为正常的Java变量名称大小写。
static void flushCaches() 冲洗所有Introspector的内部缓存。
static void flushFromCaches(类<?> clz) 刷新内部缓存信息给一个给定的类。
static BeanInfo getBeanInfo(类<?> beanClass) 内省Java Bean并了解其所有属性,暴露的方法和事件。
static BeanInfo getBeanInfo(类<?> beanClass, 类<?> stopClass) 内省Java bean并了解其属性,暴露的方法,低于给定的“停止”点。
static BeanInfo getBeanInfo(类<?> beanClass, 类<?> stopClass, int flags) 对Java Bean进行内省,并了解其所有属性,暴露的方法和事件,低于给定的 stopClass点,受到一些控制 flags 。
static BeanInfo getBeanInfo(类<?> beanClass, int flags) 对Java bean进行内省,并了解其所有属性,公开方法和事件,并遵守一些控制标志。
static String[] getBeanInfoSearchPath() 获取将用于查找BeanInfo类的包名称列表。
static void setBeanInfoSearchPath(String[] path) 更改将用于查找BeanInfo类的包名称列表。

2.3.BeanInfo介绍

JDK原文:

  • 使用BeanInfo界面创建一个BeanInfo类,并提供关于bean的方法,属性,事件和其他功能的显式信息。
  • 在开发您的bean时,您可以实现应用任务所需的bean功能,省略其余的BeanInfo功能。
  • 它们将通过自动分析获得,通过使用低级反射的bean方法和应用标准设计模式。 您有机会通过各种描述符类提供其他bean信息。

关键方法介绍:


















修饰符 返回类型 方法名称和参数 描述
PropertyDescriptor[] getPropertyDescriptors() 返回bean的所有属性的描述符。

2.4用反射实现转换

实体类:

  1. package com.sky.dto;
  2. import lombok.AllArgsConstructor;
  3. import lombok.Data;
  4. import lombok.NoArgsConstructor;
  5. @Data
  6. @AllArgsConstructor
  7. @NoArgsConstructor
  8. public class UserDTO {
  9. private Long id;
  10. private String nickName;
  11. private String icon;
  12. }

方法封装:
反射知识介绍:

  1. // 利用反射调用构造器实例化对象
  2. Object object = beanClass.getDeclaredConstructor().newInstance();
  3. // 通过实例化对象的class对象,获取所有的字段
  4. Field[] fields = object.getClass().getDeclaredFields();
  5. // 返回属性字段的修饰符
  6. int mod = field.getModifiers();

关键方法:

  1. public Object mapToBean(Map<String,Object> map,Class<?> beanClass) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
  2. // 利用反射调用构造器实例化对象
  3. Object object = beanClass.getDeclaredConstructor().newInstance();
  4. // 通过实例化对象的class对象,获取所有的字段
  5. Field[] fields = object.getClass().getDeclaredFields();
  6. for (Field field : fields) {
  7. // 返回属性字段的修饰符
  8. int mod = field.getModifiers();
  9. // 如果是静态或者final修饰的不需要添加
  10. if (Modifier.isStatic(mod)|| Modifier.isFinal(mod)){
  11. continue;
  12. }
  13. // 暴力获取私有属性
  14. field.setAccessible(true);
  15. // 相当于object.setterField()
  16. field.set(object,map.get(field.getName()));
  17. }
  18. return object;
  19. }

2.5.利用Introspector(内省)的方式转换

  1. public Object mapToBean2(Map<String,Object> map,Class<?> beanClass) throws Exception{
  2. // 利用class对象调用构造器实例化对象
  3. Object object = beanClass.getDeclaredConstructor().newInstance();
  4. // 内省Java bean并了解其属性,暴露的方法,==简单来说就是将属性封装到了BeanInfo里面==
  5. BeanInfo beanInfo = Introspector.getBeanInfo(object.getClass());
  6. // 返回bean的所有属性的描述符。
  7. PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
  8. for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
  9. /**
  10. * java.beans.PropertyDescriptor[
  11. * name=icon; values={expert=false; visualUpdate=false; hidden=false;
  12. * enumerationValues=[Ljava.lang.Object;@75c77add; required=false};
  13. * propertyType=class java.lang.String; readMethod=public java.lang.String com.sky.dto.UserDTO.getIcon();
  14. * writeMethod=public void com.sky.dto.UserDTO.setIcon(java.lang.String)]
  15. */
  16. System.out.println(propertyDescriptor);
  17. // 获取属性的setter方法
  18. Method setter = propertyDescriptor.getWriteMethod();
  19. if (setter!=null){
  20. // 获取值
  21. Object o = map.get(propertyDescriptor.getName());
  22. if (o!=null){
  23. // 利用反射将属性赋值
  24. setter.invoke(object,o);
  25. }
  26. }
  27. }
  28. return object;
  29. }

发表评论

表情:
评论列表 (有 0 条评论,151人围观)

还没有评论,来说两句吧...

相关阅读