Procházet zdrojové kódy

优化实体属性复制

zhouhao před 8 roky
rodič
revize
82cfaefd1c

+ 3 - 8
hsweb-commons/hsweb-commons-entity/src/main/java/org/hswebframework/web/commons/entity/TreeSupportEntity.java

@@ -21,7 +21,6 @@ package org.hswebframework.web.commons.entity;
 
 import org.hswebframework.web.id.IDGenerator;
 import org.hswebframwork.utils.RandomUtil;
-import org.hswebframwork.utils.StringUtils;
 
 import java.math.BigDecimal;
 import java.util.*;
@@ -52,11 +51,6 @@ public interface TreeSupportEntity<PK> extends GenericEntity<PK> {
 
     void setLevel(Integer level);
 
-    default void setLevelFromPath() {
-        if (getPath() != null)
-            setLevel(getPath().split("-").length);
-    }
-
     <T extends TreeSupportEntity<PK>> List<T> getChildren();
 
     /**
@@ -85,7 +79,8 @@ public interface TreeSupportEntity<PK> extends GenericEntity<PK> {
         List<T> children = parent.getChildren();
         if (parent.getPath() == null) {
             parent.setPath(RandomUtil.randomChar(4));
-            parent.setLevelFromPath();
+            if (parent.getPath() != null)
+                parent.setLevel(parent.getPath().split("-").length);
         }
         if (children != null) {
             PK pid = parent.getId();
@@ -104,7 +99,7 @@ public interface TreeSupportEntity<PK> extends GenericEntity<PK> {
                 }
                 child.setParentId(pid);
                 child.setPath(parent.getPath() + "-" + RandomUtil.randomChar(4));
-                child.setLevelFromPath();
+                child.setLevel(child.getPath().split("-").length);
                 target.add(child);
                 expandTree2List(child, target, idGenerator);
             }

+ 65 - 29
hsweb-commons/hsweb-commons-entity/src/main/java/org/hswebframework/web/commons/entity/factory/MapperEntityFactory.java

@@ -18,23 +18,27 @@
 
 package org.hswebframework.web.commons.entity.factory;
 
-import org.apache.commons.beanutils.BeanUtils;
+import com.alibaba.fastjson.JSON;
 import org.hswebframework.web.NotFoundException;
+import org.hswebframwork.utils.ClassUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.lang.reflect.Modifier;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Objects;
 import java.util.function.Supplier;
 
 /**
  * @author zhouhao
  * @since 3.0
  */
+@SuppressWarnings("unchecked")
 public class MapperEntityFactory implements EntityFactory {
-    private Map<Class, Mapper> realTypeMapper = new HashMap<>();
-    private Logger             logger         = LoggerFactory.getLogger(this.getClass());
+    private Map<Class, Mapper>          realTypeMapper = new HashMap<>();
+    private Logger                      logger         = LoggerFactory.getLogger(this.getClass());
+    private Map<String, PropertyCopier> copierCache    = new HashMap<>();
 
     public MapperEntityFactory() {
     }
@@ -48,45 +52,74 @@ public class MapperEntityFactory implements EntityFactory {
         return this;
     }
 
+    public MapperEntityFactory addCopier(PropertyCopier copier) {
+        Class source = ClassUtils.getGenericType(copier.getClass(), 0);
+        Class target = ClassUtils.getGenericType(copier.getClass(), 1);
+        if (source == null || source == Object.class) {
+            throw new UnsupportedOperationException("generic type " + source + " not support");
+        }
+        if (target == null || target == Object.class) {
+            throw new UnsupportedOperationException("generic type " + target + " not support");
+        }
+        addCopier(source, target, copier);
+        return this;
+    }
+
+    public <S, T> MapperEntityFactory addCopier(Class<S> source, Class<T> target, PropertyCopier<S, T> copier) {
+        copierCache.put(getCopierCacheKey(source, target), copier);
+        return this;
+    }
+
+    private String getCopierCacheKey(Class source, Class target) {
+        return source.getName().concat("->").concat(target.getName());
+
+    }
+
     @Override
     public <S, T> T copyProperties(S source, T target) {
+        Objects.requireNonNull(source);
+        Objects.requireNonNull(target);
         try {
-            // TODO: 17-3-30 应该设计为可自定义
-            BeanUtils.copyProperties(target, source);
+            PropertyCopier<S, T> copier = copierCache.<S, T>get(getCopierCacheKey(source.getClass(), target.getClass()));
+            if (null != copier) return copier.copyProperties(source, target);
+
+            return JSON.parseObject(JSON.toJSONString(source), (Class<T>) target.getClass());
         } catch (Exception e) {
             logger.warn("copy properties error", e);
         }
         return target;
     }
 
+    protected <T> Mapper<T> initCache(Class<T> beanClass) {
+        Mapper<T> mapper = null;
+        Class<T> realType = null;
+        if (!Modifier.isInterface(beanClass.getModifiers()) && !Modifier.isAbstract(beanClass.getModifiers())) {
+            realType = beanClass;
+        }
+        //尝试使用 Simple类,如: package.SimpleUserBean
+        if (realType == null) {
+            String simpleClassName = beanClass.getPackage().getName().concat(".Simple").concat(beanClass.getSimpleName());
+            try {
+                realType = (Class<T>) Class.forName(simpleClassName);
+            } catch (ClassNotFoundException e) {
+                throw new NotFoundException(e.getMessage());
+            }
+        }
+        if (realType != null) {
+            mapper = new Mapper<>(realType, new DefaultInstanceGetter(realType));
+            realTypeMapper.put(beanClass, mapper);
+        }
+        return mapper;
+    }
+
     @Override
-    @SuppressWarnings("unchecked")
     public <T> T newInstance(Class<T> beanClass) {
         if (beanClass == null) return null;
         Mapper<T> mapper = realTypeMapper.get(beanClass);
         if (mapper != null) return mapper.getInstanceGetter().get();
-        synchronized (beanClass) {
-            mapper = realTypeMapper.get(beanClass);
-            if (mapper != null) return mapper.getInstanceGetter().get();
-            Class<T> realType = null;
-            if (!Modifier.isInterface(beanClass.getModifiers()) && !Modifier.isAbstract(beanClass.getModifiers())) {
-                realType = beanClass;
-            }
-            //尝试使用 Simple类,如: package.SimpleUserBean
-            if (realType == null) {
-                String simpleClassName = beanClass.getPackage().getName().concat(".Simple").concat(beanClass.getSimpleName());
-                try {
-                    realType = (Class<T>) Class.forName(simpleClassName);
-                } catch (ClassNotFoundException e) {
-                    throw new NotFoundException(e.getMessage());
-                }
-            }
-            if (realType != null) {
-                mapper = new Mapper<>(realType, new DefaultInstanceGetter(realType));
-                realTypeMapper.put(beanClass, mapper);
-                return mapper.getInstanceGetter().get();
-            }
-        }
+        mapper = initCache(beanClass);
+        if (mapper != null) return mapper.getInstanceGetter().get();
+
         throw new NotFoundException("can't create instance for " + beanClass);
     }
 
@@ -97,7 +130,10 @@ public class MapperEntityFactory implements EntityFactory {
         if (null != mapper) {
             return mapper.getTarget();
         }
-        return null;
+        mapper = initCache(beanClass);
+        if (mapper != null)
+            return mapper.getTarget();
+        return beanClass;
     }
 
     public static class Mapper<T> {

+ 11 - 0
hsweb-commons/hsweb-commons-entity/src/main/java/org/hswebframework/web/commons/entity/factory/PropertyCopier.java

@@ -0,0 +1,11 @@
+package org.hswebframework.web.commons.entity.factory;
+
+/**
+ * 属性复制接口,用于自定义属性复制
+ *
+ * @author zhouhao
+ * @since 3.0
+ */
+public interface PropertyCopier<S, T> {
+    T copyProperties(S source, T target);
+}