xiejun
2024-11-01 80b6cbfc9c861469146318d0b3dd5f8b8b525b8a
Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/utils/BeanUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,424 @@
/*
 *      Copyright (c) 2018-2028, DreamLu All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: DreamLu å¢æ˜¥æ¢¦ (596392912@qq.com)
 */
package org.springblade.core.tool.utils;
import org.springblade.core.tool.beans.BeanProperty;
import org.springblade.core.tool.beans.BladeBeanCopier;
import org.springblade.core.tool.beans.BladeBeanMap;
import org.springblade.core.tool.convert.BladeConverter;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyAccessorFactory;
import org.springframework.cglib.beans.BeanGenerator;
import org.springframework.lang.Nullable;
import java.util.*;
/**
 * å®žä½“工具类
 *
 * @author L.cm
 */
public class BeanUtil extends org.springframework.beans.BeanUtils {
   /**
    * å®žä¾‹åŒ–对象
    *
    * @param clazz ç±»
    * @param <T>   æ³›åž‹æ ‡è®°
    * @return å¯¹è±¡
    */
   @SuppressWarnings("unchecked")
   public static <T> T newInstance(Class<?> clazz) {
      return (T) instantiateClass(clazz);
   }
   /**
    * å®žä¾‹åŒ–对象
    *
    * @param clazzStr ç±»å
    * @param <T>      æ³›åž‹æ ‡è®°
    * @return å¯¹è±¡
    */
   public static <T> T newInstance(String clazzStr) {
      try {
         Class<?> clazz = ClassUtil.forName(clazzStr, null);
         return newInstance(clazz);
      } catch (ClassNotFoundException e) {
         throw new RuntimeException(e);
      }
   }
   /**
    * èŽ·å–Bean的属性, æ”¯æŒ propertyName å¤šçº§ ï¼štest.user.name
    *
    * @param bean         bean
    * @param propertyName å±žæ€§å
    * @return å±žæ€§å€¼
    */
   @Nullable
   public static Object getProperty(@Nullable Object bean, String propertyName) {
      if (bean == null) {
         return null;
      }
      BeanWrapper beanWrapper = PropertyAccessorFactory.forBeanPropertyAccess(bean);
      return beanWrapper.getPropertyValue(propertyName);
   }
   /**
    * è®¾ç½®Bean属性, æ”¯æŒ propertyName å¤šçº§ ï¼štest.user.name
    *
    * @param bean         bean
    * @param propertyName å±žæ€§å
    * @param value        å±žæ€§å€¼
    */
   public static void setProperty(Object bean, String propertyName, Object value) {
      Objects.requireNonNull(bean, "bean Could not null");
      BeanWrapper beanWrapper = PropertyAccessorFactory.forBeanPropertyAccess(bean);
      beanWrapper.setPropertyValue(propertyName, value);
   }
   /**
    * æ·±å¤åˆ¶
    *
    * <p>
    * æ”¯æŒ map bean
    * </p>
    *
    * @param source æºå¯¹è±¡
    * @param <T>    æ³›åž‹æ ‡è®°
    * @return T
    */
   @SuppressWarnings("unchecked")
   @Nullable
   public static <T> T clone(@Nullable T source) {
      if (source == null) {
         return null;
      }
      return (T) BeanUtil.copy(source, source.getClass());
   }
   /**
    * copy å¯¹è±¡å±žæ€§ï¼Œé»˜è®¤ä¸ä½¿ç”¨Convert
    *
    * <p>
    * æ”¯æŒ map bean copy
    * </p>
    *
    * @param source æºå¯¹è±¡
    * @param clazz  ç±»å
    * @param <T>    æ³›åž‹æ ‡è®°
    * @return T
    */
   @Nullable
   public static <T> T copy(@Nullable Object source, Class<T> clazz) {
      if (source == null) {
         return null;
      }
      return BeanUtil.copy(source, source.getClass(), clazz);
   }
   /**
    * copy å¯¹è±¡å±žæ€§ï¼Œé»˜è®¤ä¸ä½¿ç”¨Convert
    *
    * <p>
    * æ”¯æŒ map bean copy
    * </p>
    *
    * @param source      æºå¯¹è±¡
    * @param sourceClazz æºç±»åž‹
    * @param targetClazz è½¬æ¢æˆçš„类型
    * @param <T>         æ³›åž‹æ ‡è®°
    * @return T
    */
   @Nullable
   public static <T> T copy(@Nullable Object source, Class sourceClazz, Class<T> targetClazz) {
      if (source == null) {
         return null;
      }
      BladeBeanCopier copier = BladeBeanCopier.create(sourceClazz, targetClazz, false);
      T to = newInstance(targetClazz);
      copier.copy(source, to, null);
      return to;
   }
   /**
    * copy åˆ—表对象,默认不使用Convert
    *
    * <p>
    * æ”¯æŒ map bean copy
    * </p>
    *
    * @param sourceList  æºåˆ—表
    * @param targetClazz è½¬æ¢æˆçš„类型
    * @param <T>         æ³›åž‹æ ‡è®°
    * @return T
    */
   public static <T> List<T> copy(@Nullable Collection<?> sourceList, Class<T> targetClazz) {
      if (sourceList == null || sourceList.isEmpty()) {
         return Collections.emptyList();
      }
      List<T> outList = new ArrayList<>(sourceList.size());
      Class<?> sourceClazz = null;
      for (Object source : sourceList) {
         if (source == null) {
            continue;
         }
         if (sourceClazz == null) {
            sourceClazz = source.getClass();
         }
         T bean = BeanUtil.copy(source, sourceClazz, targetClazz);
         outList.add(bean);
      }
      return outList;
   }
   /**
    * æ‹·è´å¯¹è±¡
    *
    * <p>
    * æ”¯æŒ map bean copy
    * </p>
    *
    * @param source     æºå¯¹è±¡
    * @param targetBean éœ€è¦èµ‹å€¼çš„对象
    */
   public static void copy(@Nullable Object source, @Nullable Object targetBean) {
      if (source == null || targetBean == null) {
         return;
      }
      BladeBeanCopier copier = BladeBeanCopier
         .create(source.getClass(), targetBean.getClass(), false);
      copier.copy(source, targetBean, null);
   }
   /**
    * æ‹·è´å¯¹è±¡ï¼Œsource å±žæ€§åš null åˆ¤æ–­ï¼ŒMap ä¸æ”¯æŒï¼Œmap ä¼šåš instanceof åˆ¤æ–­ï¼Œä¸ä¼š
    *
    * <p>
    * æ”¯æŒ bean copy
    * </p>
    *
    * @param source     æºå¯¹è±¡
    * @param targetBean éœ€è¦èµ‹å€¼çš„对象
    */
   public static void copyNonNull(@Nullable Object source, @Nullable Object targetBean) {
      if (source == null || targetBean == null) {
         return;
      }
      BladeBeanCopier copier = BladeBeanCopier
         .create(source.getClass(), targetBean.getClass(), false, true);
      copier.copy(source, targetBean, null);
   }
   /**
    * æ‹·è´å¯¹è±¡å¹¶å¯¹ä¸åŒç±»åž‹å±žæ€§è¿›è¡Œè½¬æ¢
    *
    * <p>
    * æ”¯æŒ map bean copy
    * </p>
    *
    * @param source æºå¯¹è±¡
    * @param targetClazz è½¬æ¢æˆçš„ç±»
    * @param <T>    æ³›åž‹æ ‡è®°
    * @return T
    */
   @Nullable
   public static <T> T copyWithConvert(@Nullable Object source, Class<T> targetClazz) {
      if (source == null) {
         return null;
      }
      return BeanUtil.copyWithConvert(source, source.getClass(), targetClazz);
   }
   /**
    * æ‹·è´å¯¹è±¡å¹¶å¯¹ä¸åŒç±»åž‹å±žæ€§è¿›è¡Œè½¬æ¢
    *
    * <p>
    * æ”¯æŒ map bean copy
    * </p>
    *
    * @param source æºå¯¹è±¡
    * @param sourceClazz æºç±»
    * @param targetClazz è½¬æ¢æˆçš„ç±»
    * @param <T>    æ³›åž‹æ ‡è®°
    * @return T
    */
   @Nullable
   public static <T> T copyWithConvert(@Nullable Object source, Class<?> sourceClazz, Class<T> targetClazz) {
      if (source == null) {
         return null;
      }
      BladeBeanCopier copier = BladeBeanCopier.create(sourceClazz, targetClazz, true);
      T to = newInstance(targetClazz);
      copier.copy(source, to, new BladeConverter(sourceClazz, targetClazz));
      return to;
   }
   /**
    * æ‹·è´åˆ—表并对不同类型属性进行转换
    *
    * <p>
    * æ”¯æŒ map bean copy
    * </p>
    *
    * @param sourceList æºå¯¹è±¡åˆ—表
    * @param targetClazz è½¬æ¢æˆçš„ç±»
    * @param <T>    æ³›åž‹æ ‡è®°
    * @return List
    */
   public static <T> List<T> copyWithConvert(@Nullable Collection<?> sourceList, Class<T> targetClazz) {
      if (sourceList == null || sourceList.isEmpty()) {
         return Collections.emptyList();
      }
      List<T> outList = new ArrayList<>(sourceList.size());
      Class<?> sourceClazz = null;
      for (Object source : sourceList) {
         if (source == null) {
            continue;
         }
         if (sourceClazz == null) {
            sourceClazz = source.getClass();
         }
         T bean = BeanUtil.copyWithConvert(source, sourceClazz, targetClazz);
         outList.add(bean);
      }
      return outList;
   }
   /**
    * Copy the property values of the given source bean into the target class.
    * <p>Note: The source and target classes do not have to match or even be derived
    * from each other, as long as the properties match. Any bean properties that the
    * source bean exposes but the target bean does not will silently be ignored.
    * <p>This is just a convenience method. For more complex transfer needs,
    *
    * @param source the source bean
    * @param targetClazz the target bean class
    * @param <T>    æ³›åž‹æ ‡è®°
    * @return T
    * @throws BeansException if the copying failed
    */
   @Nullable
   public static <T> T copyProperties(@Nullable Object source, Class<T> targetClazz) throws BeansException {
      if (source == null) {
         return null;
      }
      T to = newInstance(targetClazz);
      BeanUtil.copyProperties(source, to);
      return to;
   }
   /**
    * Copy the property values of the given source bean into the target class.
    * <p>Note: The source and target classes do not have to match or even be derived
    * from each other, as long as the properties match. Any bean properties that the
    * source bean exposes but the target bean does not will silently be ignored.
    * <p>This is just a convenience method. For more complex transfer needs,
    *
    * @param sourceList the source list bean
    * @param targetClazz the target bean class
    * @param <T>    æ³›åž‹æ ‡è®°
    * @return List
    * @throws BeansException if the copying failed
    */
   public static <T> List<T> copyProperties(@Nullable Collection<?> sourceList, Class<T> targetClazz) throws BeansException {
      if (sourceList == null || sourceList.isEmpty()) {
         return Collections.emptyList();
      }
      List<T> outList = new ArrayList<>(sourceList.size());
      for (Object source : sourceList) {
         if (source == null) {
            continue;
         }
         T bean = BeanUtil.copyProperties(source, targetClazz);
         outList.add(bean);
      }
      return outList;
   }
   /**
    * å°†å¯¹è±¡è£…成map形式
    *
    * @param bean æºå¯¹è±¡
    * @return {Map}
    */
   @SuppressWarnings("unchecked")
   public static Map<String, Object> toMap(@Nullable Object bean) {
      if (bean == null) {
         return new HashMap<>(0);
      }
      return BladeBeanMap.create(bean);
   }
   /**
    * å°†map è½¬ä¸º bean
    *
    * @param beanMap   map
    * @param valueType å¯¹è±¡ç±»åž‹
    * @param <T>       æ³›åž‹æ ‡è®°
    * @return {T}
    */
   public static <T> T toBean(Map<String, Object> beanMap, Class<T> valueType) {
      Objects.requireNonNull(beanMap, "beanMap Could not null");
      T to = newInstance(valueType);
      if (beanMap.isEmpty()) {
         return to;
      }
      BeanUtil.copy(beanMap, to);
      return to;
   }
   /**
    * ç»™ä¸€ä¸ªBean添加字段
    *
    * @param superBean çˆ¶çº§Bean
    * @param props     æ–°å¢žå±žæ€§
    * @return {Object}
    */
   @Nullable
   public static Object generator(@Nullable Object superBean, BeanProperty... props) {
      if (superBean == null) {
         return null;
      }
      Class<?> superclass = superBean.getClass();
      Object genBean = generator(superclass, props);
      BeanUtil.copy(superBean, genBean);
      return genBean;
   }
   /**
    * ç»™ä¸€ä¸ªclass添加字段
    *
    * @param superclass çˆ¶çº§
    * @param props      æ–°å¢žå±žæ€§
    * @return {Object}
    */
   public static Object generator(Class<?> superclass, BeanProperty... props) {
      BeanGenerator generator = new BeanGenerator();
      generator.setSuperclass(superclass);
      generator.setUseCache(true);
      for (BeanProperty prop : props) {
         generator.addProperty(prop.getName(), prop.getType());
      }
      return generator.create();
   }
}