All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.gitee.easyopen.util.ReflectionUtil Maven / Gradle / Ivy

package com.gitee.easyopen.util;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.gitee.easyopen.annotation.ApiService;
import org.springframework.beans.FatalBeanException;
import org.springframework.context.ApplicationContext;

/**
 * 反射相关
 * @author tanghc
 */
public class ReflectionUtil {

    public static final String PREFIX_SET = "set";

    private static final String[] EMPTY_STRING_ARRAY = {};

    private static Map> classGenricTypeCache = new HashMap<>(16);

    /** key:obj.getClass().getName() + genericClass.getName() */
    private static Map genericTypeFieldCache = new HashMap<>();
    
    /**
     * 设置某个字段的值
     * @param target 实体类,必须有字段的set方法
     * @param fieldName 字段名
     * @param val 值
     */
    public static void invokeFieldValue(Object target,String fieldName, Object val) {
        String setMethodName = getSetMethodName(fieldName);
        Method[] methods = target.getClass().getDeclaredMethods();
        for (Method method : methods) {
            String methodName = method.getName();
            Class[] methodParams = method.getParameterTypes();
            
            if (setMethodName.equals(methodName)) {
                // 能否拷贝
                boolean canCopy =
                        // 并且只有一个参数
                        methodParams.length == 1
                                // val是methodParams[0]或他的子类
                        && methodParams[0].isInstance(val) || Number.class.isInstance(val);
                
                if (canCopy) {
                    try {
                        if (!Modifier.isPublic(method.getDeclaringClass().getModifiers())) {
                            method.setAccessible(true);
                        }
                        method.invoke(target, val);
                        break;
                    } catch (Throwable ex) {
                        throw new FatalBeanException(
                                "Could not set property '" + fieldName + "' value to target", ex);
                    }
                }
            }
        }
    }

    /**
     * 返回实体类中具有指定泛型的字段
     * @param obj 实体类
     * @param genericClass 指定泛型
     * @return 没有返回null
     */
    public static Field getListFieldWithGeneric(Object obj, Class genericClass) {
        Class objClass = obj.getClass();
        String key = objClass.getName() + genericClass.getName();
        Field value = genericTypeFieldCache.get(key);
        if (value != null) {
            return value;
        }
        Field[] fields = objClass.getDeclaredFields();
        for (Field field : fields) {
            Type genericType = getListGenericType(field);
            if (genericType == genericClass) {
                genericTypeFieldCache.put(key, field);
                return field;
            }
        }
        return null;
    }

    /**
     * 返回集合字段的泛型类型。
* 如:List<User> list;返回User.class * * @param field * 类中的一个属性 * @return 返回类型 */ public static Type getListGenericType(Field field) { if (isListType(field.getType())) { Type genericType = field.getGenericType(); if (genericType instanceof ParameterizedType) { Type[] params = ((ParameterizedType) genericType).getActualTypeArguments(); if (params.length == 1) { return params[0]; } } } return Object.class; } public static boolean isListType(Type type) { return type == List.class; } /** * 返回set方法名。name -> setName * @param fieldName * @return 返回方法名 */ public static String getSetMethodName(String fieldName) { return PREFIX_SET + Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1); } /** * 构建字段名称 * @param methodName 根据get或set方法返回字段名称 * @return 字段名称 */ public static String buildFieldName(String methodName) { return methodName.substring(3, 4).toLowerCase() + methodName.substring(4); } /** * 返回定义类时的泛型参数的类型.
* 如:定义一个BookManager类
* {@literal public BookManager extends GenricManager}{...} *
* 调用getSuperClassGenricType(getClass(),0)将返回Book的Class类型
* 调用getSuperClassGenricType(getClass(),1)将返回Address的Class类型 * * @param clazz 从哪个类中获取 * @param index 泛型参数索引,从0开始 * @return 返回泛型参数类型 */ public static Class getSuperClassGenricType(Class clazz, int index) throws IndexOutOfBoundsException { String cacheKey = clazz.getName() + index; Class cachedClass = classGenricTypeCache.get(cacheKey); if (cachedClass != null) { return cachedClass; } Type genType = clazz.getGenericSuperclass(); // 没有泛型参数 if (!(genType instanceof ParameterizedType)) { throw new RuntimeException("class " + clazz.getName() + " 没有指定父类泛型"); } else { Type[] params = ((ParameterizedType) genType).getActualTypeArguments(); if (index >= params.length || index < 0) { throw new RuntimeException("泛型索引不正确,index:" + index); } if (!(params[index] instanceof Class)) { throw new RuntimeException(params[index] + "不是Class类型"); } Class retClass = (Class) params[index]; // 缓存起来 classGenricTypeCache.put(cacheKey, retClass); return retClass; } } /** * 找到所有ApiService的类名 * @param ctx ApplicationContext * @return 返回类名称数组 */ public static String[] findApiServiceNames(ApplicationContext ctx) { return findBeanNamesByAnnotationClass(ctx, ApiService.class); } /** * 找到所有被注解标记的类名 * @param ctx ApplicationContext * @param annotationClass 注解class * @return 返回类名称数组,没有返回空数组 */ public static String[] findBeanNamesByAnnotationClass(ApplicationContext ctx, Class annotationClass) { String[] beans = ctx.getBeanNamesForAnnotation(annotationClass); // 如果没找到,去父容器找 if (beans == null || beans.length == 0) { ApplicationContext parentCtx = ctx.getParent(); if (parentCtx != null) { beans = parentCtx.getBeanNamesForAnnotation(annotationClass); } } if (beans == null) { beans = EMPTY_STRING_ARRAY; } return beans; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy