¶Ô±ÈÐÂÎļþ |
| | |
| | | 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)); |
| | | } |
| | | } |