xiejun
2024-11-01 80b6cbfc9c861469146318d0b3dd5f8b8b525b8a
Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/convert/BladeConverter.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,77 @@
package org.springblade.core.tool.convert;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.tool.function.CheckedFunction;
import org.springblade.core.tool.utils.ClassUtil;
import org.springblade.core.tool.utils.ConvertUtil;
import org.springblade.core.tool.utils.ReflectUtil;
import org.springblade.core.tool.utils.Unchecked;
import org.springframework.cglib.core.Converter;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.lang.Nullable;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
 * ç»„合 spring cglib Converter å’Œ spring ConversionService
 *
 * @author L.cm
 */
@Slf4j
@AllArgsConstructor
public class BladeConverter implements Converter {
   private static final ConcurrentMap<String, TypeDescriptor> TYPE_CACHE = new ConcurrentHashMap<>();
   private final Class<?> sourceClazz;
   private final Class<?> targetClazz;
   /**
    * cglib convert
    *
    * @param value     æºå¯¹è±¡å±žæ€§
    * @param target    ç›®æ ‡å¯¹è±¡å±žæ€§ç±»
    * @param fieldName ç›®æ ‡çš„field名,原为 set æ–¹æ³•名,BladeBeanCopier é‡Œåšäº†æ›´æ”¹
    * @return {Object}
    */
   @Override
   @Nullable
   public Object convert(Object value, Class target, final Object fieldName) {
      if (value == null) {
         return null;
      }
      // ç±»åž‹ä¸€æ ·ï¼Œä¸éœ€è¦è½¬æ¢
      if (ClassUtil.isAssignableValue(target, value)) {
         return value;
      }
      try {
         TypeDescriptor targetDescriptor = BladeConverter.getTypeDescriptor(targetClazz, (String) fieldName);
         // 1. åˆ¤æ–­ sourceClazz ä¸º Map
         if (Map.class.isAssignableFrom(sourceClazz)) {
            return ConvertUtil.convert(value, targetDescriptor);
         } else {
            TypeDescriptor sourceDescriptor = BladeConverter.getTypeDescriptor(sourceClazz, (String) fieldName);
            return ConvertUtil.convert(value, sourceDescriptor, targetDescriptor);
         }
      } catch (Throwable e) {
         log.warn("BladeConverter error", e);
         return null;
      }
   }
   private static TypeDescriptor getTypeDescriptor(final Class<?> clazz, final String fieldName) {
      String srcCacheKey = clazz.getName() + fieldName;
      // å¿½ç•¥æŠ›å‡ºå¼‚常的函数,定义完整泛型,避免编译问题
      CheckedFunction<String, TypeDescriptor> uncheckedFunction = (key) -> {
         // è¿™é‡Œ property ç†è®ºä¸Šä¸ä¼šä¸º null
         Field field = ReflectUtil.getField(clazz, fieldName);
         if (field == null) {
            throw new NoSuchFieldException(fieldName);
         }
         return new TypeDescriptor(field);
      };
      return TYPE_CACHE.computeIfAbsent(srcCacheKey, Unchecked.function(uncheckedFunction));
   }
}