package com.alibaba.excel.util; import java.lang.ref.SoftReference; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.concurrent.ConcurrentHashMap; import com.alibaba.excel.annotation.ExcelIgnore; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.exception.ExcelCommonException; import com.alibaba.excel.metadata.BaseRowModel; /** * Class utils * * @author Jiaju Zhuang **/ public class ClassUtils { private static final Map> FIELD_CACHE = new ConcurrentHashMap>(); public static void declaredFields(Class clazz, List defaultFieldList, Map customFiledMap, Map ignoreMap, Boolean convertAllFiled) { FieldCache fieldCache = getFieldCache(clazz, convertAllFiled); if (fieldCache != null) { defaultFieldList.addAll(fieldCache.getDefaultFieldList()); customFiledMap.putAll(fieldCache.getCustomFiledMap()); ignoreMap.putAll(fieldCache.getIgnoreMap()); } } public static void declaredFields(Class clazz, List fieldList, Boolean convertAllFiled) { FieldCache fieldCache = getFieldCache(clazz, convertAllFiled); if (fieldCache != null) { fieldList.addAll(fieldCache.getAllFieldList()); } } private static FieldCache getFieldCache(Class clazz, Boolean convertAllFiled) { if (clazz == null) { return null; } SoftReference fieldCacheSoftReference = FIELD_CACHE.get(clazz); if (fieldCacheSoftReference != null && fieldCacheSoftReference.get() != null) { return fieldCacheSoftReference.get(); } synchronized (clazz) { fieldCacheSoftReference = FIELD_CACHE.get(clazz); if (fieldCacheSoftReference != null && fieldCacheSoftReference.get() != null) { return fieldCacheSoftReference.get(); } declaredFields(clazz, convertAllFiled); } return FIELD_CACHE.get(clazz).get(); } private static void declaredFields(Class clazz, Boolean convertAllFiled) { List tempFieldList = new ArrayList(); Class tempClass = clazz; // When the parent class is null, it indicates that the parent class (Object class) has reached the top // level. while (tempClass != null && tempClass != BaseRowModel.class) { Collections.addAll(tempFieldList, tempClass.getDeclaredFields()); // Get the parent class and give it to yourself tempClass = tempClass.getSuperclass(); } // Screening of field List defaultFieldList = new ArrayList(); Map customFiledMap = new TreeMap(); List allFieldList = new ArrayList(); Map ignoreMap = new HashMap(16); ExcelIgnoreUnannotated excelIgnoreUnannotated = (ExcelIgnoreUnannotated)clazz.getAnnotation(ExcelIgnoreUnannotated.class); for (Field field : tempFieldList) { ExcelIgnore excelIgnore = field.getAnnotation(ExcelIgnore.class); if (excelIgnore != null) { ignoreMap.put(field.getName(), field); continue; } ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class); boolean noExcelProperty = excelProperty == null && ((convertAllFiled != null && !convertAllFiled) || excelIgnoreUnannotated != null); if (noExcelProperty) { ignoreMap.put(field.getName(), field); continue; } boolean isStaticFinalOrTransient = (Modifier.isStatic(field.getModifiers()) && Modifier.isFinal(field.getModifiers())) || Modifier.isTransient(field.getModifiers()); if (excelProperty == null && isStaticFinalOrTransient) { ignoreMap.put(field.getName(), field); continue; } if (excelProperty == null || excelProperty.index() < 0) { defaultFieldList.add(field); allFieldList.add(field); continue; } if (customFiledMap.containsKey(excelProperty.index())) { throw new ExcelCommonException("The index of '" + customFiledMap.get(excelProperty.index()).getName() + "' and '" + field.getName() + "' must be inconsistent"); } customFiledMap.put(excelProperty.index(), field); } List allWriteFieldList = new ArrayList(customFiledMap.values()); allWriteFieldList.addAll(allFieldList); FIELD_CACHE.put(clazz, new SoftReference(new FieldCache(defaultFieldList, customFiledMap, allWriteFieldList, ignoreMap))); } private static class FieldCache { private List defaultFieldList; private Map customFiledMap; private List allFieldList; private Map ignoreMap; public FieldCache(List defaultFieldList, Map customFiledMap, List allFieldList, Map ignoreMap) { this.defaultFieldList = defaultFieldList; this.customFiledMap = customFiledMap; this.allFieldList = allFieldList; this.ignoreMap = ignoreMap; } public List getDefaultFieldList() { return defaultFieldList; } public Map getCustomFiledMap() { return customFiledMap; } public List getAllFieldList() { return allFieldList; } public Map getIgnoreMap() { return ignoreMap; } } }