|
|
package com.yoho.datasync.consumer.handler.helper;
|
|
|
|
|
|
import com.yoho.datasync.consumer.handler.annotation.ClassTransfer;
|
|
|
import com.yoho.datasync.consumer.handler.annotation.FieldTransfer;
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
import org.springframework.beans.factory.config.BeanDefinition;
|
|
|
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
|
|
|
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
|
|
import org.springframework.stereotype.Component;
|
|
|
|
|
|
import javax.annotation.PostConstruct;
|
|
|
import java.lang.reflect.Field;
|
|
|
import java.util.*;
|
|
|
|
|
|
@Component
|
|
|
public class ClassTransferScanner {
|
|
|
|
|
|
private ClassPathScanningCandidateComponentProvider provider;
|
|
|
|
|
|
private static final Logger logger = LoggerFactory.getLogger(ClassTransferScanner.class);
|
|
|
|
|
|
public static final Map<Class, Map<Class,Object>> targetInfoMap = new HashMap<>();
|
|
|
|
|
|
public static final Map<Class, Map<Field,Field>> targetFieldMap = new HashMap<>();
|
|
|
|
|
|
private final static String path = "com.yoho.datasync.consumer.handler.model";
|
|
|
|
|
|
public ClassTransferScanner() {
|
|
|
provider = new ClassPathScanningCandidateComponentProvider(false);
|
|
|
provider.addIncludeFilter(new AnnotationTypeFilter(ClassTransfer.class));
|
|
|
}
|
|
|
|
|
|
@PostConstruct
|
|
|
void scan() throws Exception{
|
|
|
List<Class<?>> results = doScan();
|
|
|
for (Class<?> clazz: results) {
|
|
|
targetInfoMap.put(clazz,getTargetObjects(clazz));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private <T> T newInstance(Class<T> clazz) {
|
|
|
try {
|
|
|
return clazz.newInstance();
|
|
|
} catch (Exception e) {
|
|
|
logger.error(e.getMessage(), e);
|
|
|
return null;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public Map<Class, Object> getTargetObjects(Class clazz) throws Exception {
|
|
|
//1、获取每个field对应的目标信息
|
|
|
Map<Field, Field> targetClassInfo = getTargetInfoFactory(clazz);
|
|
|
|
|
|
//2、初始化实例
|
|
|
Map<Class, Object> instanceMap = new HashMap<>();
|
|
|
for (Map.Entry<Field, Field> entry : targetClassInfo.entrySet()) {
|
|
|
Field field = entry.getKey();
|
|
|
Field targetField = entry.getValue();
|
|
|
Object traget = instanceMap.computeIfAbsent(targetField.getDeclaringClass(), a -> newInstance(a));
|
|
|
if (traget != null) {
|
|
|
field.setAccessible(true);
|
|
|
targetField.setAccessible(true);
|
|
|
targetField.set(traget, field.get(newInstance(clazz)));
|
|
|
}
|
|
|
}
|
|
|
return instanceMap;
|
|
|
}
|
|
|
|
|
|
private Map<Field, Field> getTargetInfoFactory(Class<?> clazz) {
|
|
|
|
|
|
//1、从缓存中获取
|
|
|
Map<Field, Field> targetInfo = targetFieldMap.get(clazz);
|
|
|
if (targetInfo != null) {
|
|
|
return targetInfo;
|
|
|
}
|
|
|
targetInfo = new HashMap<>();
|
|
|
targetFieldMap.put(clazz, targetInfo);
|
|
|
|
|
|
//2、解析ClassTransfer
|
|
|
ClassTransfer classTransfer = clazz.getAnnotation(ClassTransfer.class);
|
|
|
if (classTransfer == null) {
|
|
|
return new HashMap<>();
|
|
|
}
|
|
|
Class<?> targetClass = classTransfer.targetClass();
|
|
|
//3、解析FieldTransfer
|
|
|
for (Field field : clazz.getDeclaredFields()) {
|
|
|
String targetFieldName = null;
|
|
|
FieldTransfer fieldTransfer = field.getAnnotation(FieldTransfer.class);
|
|
|
if (fieldTransfer != null) {
|
|
|
if(!fieldTransfer.targetClass().isAssignableFrom(ClassTransfer.class) ){
|
|
|
|
|
|
targetClass = fieldTransfer.targetClass();
|
|
|
}
|
|
|
targetFieldName = StringUtils.isBlank(fieldTransfer.targetFieldName()) ? field.getName() : fieldTransfer.targetFieldName();
|
|
|
}
|
|
|
if (targetFieldName != null) {
|
|
|
Field targetField = getField(targetClass, targetFieldName);
|
|
|
if (targetField != null) {
|
|
|
targetInfo.put(field, targetField);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//4、返回解析结果
|
|
|
return targetInfo;
|
|
|
}
|
|
|
|
|
|
private Field getField(Class<?> clazz, String fieldName) {
|
|
|
try {
|
|
|
return clazz.getDeclaredField(fieldName);
|
|
|
} catch (Exception e) {
|
|
|
logger.error(e.getMessage(), e);
|
|
|
return null;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private List<Class<?>> doScan() {
|
|
|
Set<BeanDefinition> beanDefinitionSet = provider.findCandidateComponents(path);
|
|
|
List<Class<?>> results = new ArrayList<>();
|
|
|
for (BeanDefinition beanDefinition : beanDefinitionSet) {
|
|
|
try {
|
|
|
results.add(Class.forName(beanDefinition.getBeanClassName()));
|
|
|
} catch (Exception e) {
|
|
|
e.printStackTrace();
|
|
|
}
|
|
|
}
|
|
|
return results;
|
|
|
}
|
|
|
|
|
|
|
|
|
} |
...
|
...
|
|