All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.micro.core.util.BeanUtil Maven / Gradle / Ivy

package cn.micro.core.util;


import cn.micro.core.exception.BizException;
import net.sf.cglib.beans.BeanMap;
import org.springframework.beans.BeanUtils;
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 org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.FastByteArrayOutputStream;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.*;

/**
 * 实体工具类
 */
public class BeanUtil extends BeanUtils {

    /**
     * 实例化对象
     *
     * @param clazz 类
     * @param    泛型标记
     * @return 对象
     */
    @SuppressWarnings("unchecked")
    public static  T newInstance(Class clazz) {
        return (T) instantiateClass(clazz);
    }

    /**
     * 实例化对象
     *
     * @param clazzStr 类名
     * @param       泛型标记
     * @return 对象
     */
    public static  T newInstance(String clazzStr) {
        return newInstance(forName(clazzStr));
    }

    /**
     * forName
     *
     * @param clazzStr 类名
     * @return Class
     */
    public static Class forName(String clazzStr) {
        try {
            return ClassUtils.forName(clazzStr, null);
        } catch (ClassNotFoundException e) {
            throw new BizException(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) {
        BeanWrapper beanWrapper = PropertyAccessorFactory.forBeanPropertyAccess(Objects.requireNonNull(bean, "bean Could not null"));
        beanWrapper.setPropertyValue(propertyName, value);
    }

    /**
     * 深度拷贝
     *
     * @param source 待拷贝的对象
     * @return 拷贝之后的对象
     */
    @Nullable
    @SuppressWarnings("unchecked")
    public static  T deepClone(@Nullable T source) {
        if (source == null) {
            return null;
        }
        FastByteArrayOutputStream fBos = new FastByteArrayOutputStream(1024);
        try (ObjectOutputStream oos = new ObjectOutputStream(fBos)) {
            oos.writeObject(source);
            oos.flush();
        } catch (IOException ex) {
            throw new IllegalArgumentException("Failed to serialize object of type: " + source.getClass(), ex);
        }
        try (ObjectInputStream ois = new ObjectInputStream(fBos.getInputStream())) {
            return (T) ois.readObject();
        } catch (IOException | ClassNotFoundException ex) {
            throw new IllegalArgumentException("Failed to deserialize object", ex);
        }
    }

    /**
     * Copy the property values of the given source bean into the target class.
     * 

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. *

This is just a convenience method. For more complex transfer needs, * * @param source the source bean * @param targetClazz the target bean class * @param 泛型标记 * @return T * @throws BeansException if the copying failed */ @Nullable public static T copyProperties(@Nullable Object source, Class targetClazz) throws BeansException { if (source == null) { return null; } T to = newInstance(targetClazz); BeanUtils.copyProperties(source, to); return to; } /** * Copy the property values of the given source bean into the target class. *

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. *

This is just a convenience method. For more complex transfer needs, * * @param sourceList the source list bean * @param targetClazz the target bean class * @param 泛型标记 * @return List * @throws BeansException if the copying failed */ public static List copyProperties(@Nullable Collection sourceList, Class targetClazz) throws BeansException { if (sourceList == null || sourceList.isEmpty()) { return Collections.emptyList(); } List 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形式,map 不可写 * * @param bean 源对象 * @return {Map} */ @SuppressWarnings("unchecked") public static Map toMap(@Nullable Object bean) { if (bean == null) { return new HashMap<>(0); } BeanMap beanMap = BeanMap.create(bean); Map objectMap = new HashMap<>(beanMap.size()); for (Object key : beanMap.keySet()) { objectMap.put(key.toString(), beanMap.get(key)); } return objectMap; } /** * 将对象装成map形式,map 可写 * * @param bean 源对象 * @return {Map} */ public static Map toNewMap(@Nullable Object bean) { return new HashMap<>(toMap(bean)); } /** * 将map 转为 bean * * @param beanMap map * @param valueType 对象类型 * @param 泛型标记 * @return {T} */ public static T toBean(Map beanMap, Class valueType) { Objects.requireNonNull(beanMap, "beanMap Could not null"); T to = newInstance(valueType); if (beanMap.isEmpty()) { return to; } BeanMap map = BeanMap.create(to); map.putAll(beanMap); return to; } /** * 给一个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(); } /** * 比较对象 * * @param src 源对象 * @param dist 新对象 * @return {BeanDiff} */ public static BeanDiff diff(final Object src, final Object dist) { Assert.notNull(src, "diff Object src is null."); Assert.notNull(src, "diff Object dist is null."); return diff(BeanUtil.toMap(src), BeanUtil.toMap(dist)); } /** * 比较Map * * @param src 源Map * @param dist 新Map * @return {BeanDiff} */ public static BeanDiff diff(final Map src, final Map dist) { Assert.notNull(src, "diff Map src is null."); Assert.notNull(src, "diff Map dist is null."); // 改变 Map difference = new HashMap<>(8); difference.putAll(src); difference.putAll(dist); difference.entrySet().removeAll(src.entrySet()); // 老值 Map oldValues = new HashMap<>(8); difference.keySet().forEach((k) -> oldValues.put(k, src.get(k))); BeanDiff diff = new BeanDiff(); diff.getFields().addAll(difference.keySet()); diff.getOldValues().putAll(oldValues); diff.getNewValues().putAll(difference); return diff; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy