LambdaReflectUtil

2020-11-23  本文已影响0人  LoWang
package com.test;

import java.beans.Introspector;
import java.io.Serializable;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;

import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.ReflectionUtils;

import com.google.common.base.CaseFormat;

import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.Setter;

public class LambdaReflectUtil {

    public static void main(String[] args) {

        Student st = new Student();
        String fieldName = LambdaReflectUtil.getName(Student::getStudentName);
        System.out.println(fieldName);

        fieldName = LambdaReflectUtil.getUnderscoreName(Student::getStudentName);
        System.out.println(fieldName);
        st.setStudentName("张三");
        st.setId(201L);
        Object obj = BeanParamBuilder.of(st).checkAndBuild(Student::getStudentName).checkAndBuild(Student::getId)
            .set("ss.classId", 999L).buildMap();
        System.out.println(obj);

        obj = BeanParamBuilder.of(st).checkAndBuild(Student::getStudentName).checkAndBuild(Student::getId)
            .set("ss.classId", 999L).buildUnderscoreMap();
        System.out.println(obj);
    }

    @RequiredArgsConstructor(staticName = "of")
    public static class BeanParamBuilder<T> {

        private final T t;
        @Setter
        private String prefix;
        private Map<String, Object> params = new HashMap<>();

        public BeanParamBuilder<T> checkAndBuild(TypeFunction<T, ?> fn) {
            String name = LambdaReflectUtil.getName(fn);
            Field field = ReflectionUtils.findField(t.getClass(), name);
            if (Objects.nonNull(field)) {
                ReflectionUtils.makeAccessible(field);
                Object value = ReflectionUtils.getField(field, t);
                if (StringUtils.isNotBlank(prefix)) {
                    name = String.format("%s_%s", prefix, name);
                }
                params.put(name, value);
            }
            return this;
        }

        public BeanParamBuilder<T> set(String key, Object value) {
            key = key.replaceAll("[.]", "_");
            params.put(key, value);
            return this;
        }

        public Map<String, Object> buildMap() {
            return params;
        }

        public Map<String, Object> buildUnderscoreMap() {
            if (MapUtils.isNotEmpty(params)) {
                Map<String, Object> converted = new HashMap<>(params.size());
                params.entrySet().stream().forEach(entry -> {
                    converted.put(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, entry.getKey()),
                        entry.getValue());
                });
                return converted;
            } else {
                return Collections.emptyMap();
            }
        }

    }

    public static <T> String getUnderscoreName(SFunction<T, ?> fn) {
        // 从function取出序列化方法
        Method writeReplaceMethod;
        try {
            writeReplaceMethod = fn.getClass().getDeclaredMethod("writeReplace");
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }

        // 从序列化方法取出序列化的lambda信息
        boolean isAccessible = writeReplaceMethod.canAccess(fn);
        writeReplaceMethod.setAccessible(Boolean.TRUE);
        SerializedLambda serializedLambda;
        try {
            serializedLambda = (SerializedLambda)writeReplaceMethod.invoke(fn);
        } catch (IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException(e);
        }
        writeReplaceMethod.setAccessible(isAccessible);

        // 从lambda信息取出method、field、class等
        String fieldName = serializedLambda.getImplMethodName().substring("get".length());
        fieldName = fieldName.replaceFirst(fieldName.charAt(0) + "", (fieldName.charAt(0) + "").toLowerCase());
        return fieldName.replaceAll("[A-Z]", "_$0").toLowerCase();
    }

    public static <T, R> String getName(TypeFunction<T, R> fn) {
        return TypeFunction.getLambdaColumnName(fn);
    }

    @Data
    public static class Student {
        private Long id;
        private String studentName;
        private String studentAge;
    }

    @FunctionalInterface
    public static interface SFunction<T, R> extends Function<T, R>, Serializable {}

    @FunctionalInterface
    public static interface TypeFunction<T, R> extends Serializable, Function<T, R> {

        /**
         * 获取列名称
         * 
         * @param lambda
         * @return String
         */
        static String getLambdaColumnName(Serializable lambda) {
            try {
                Method method = lambda.getClass().getDeclaredMethod("writeReplace");
                method.setAccessible(Boolean.TRUE);
                SerializedLambda serializedLambda = (SerializedLambda)method.invoke(lambda);
                String getter = serializedLambda.getImplMethodName();
                String fieldName = Introspector.decapitalize(getter.replace("get", ""));
                return fieldName;
            } catch (ReflectiveOperationException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

上一篇下一篇

猜你喜欢

热点阅读