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

com.github.life.lab.leisure.common.utils.reflect.FastClasses Maven / Gradle / Ivy

There is a newer version: 0.0.12.RELEASE
Show newest version
package com.github.life.lab.leisure.common.utils.reflect;

import com.github.life.lab.leisure.common.utils.ClassUtils;
import net.sf.cglib.reflect.FastClass;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.beans.BeanInfo;
import java.beans.PropertyDescriptor;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * FastClasses
 *
 * @author weichao.li ([email protected])
 * @date 2018/6/9
 */
public class FastClasses implements ColorsClass {

    private static final Logger LOGGER = LoggerFactory.getLogger(ClassUtils.class);

    private Class clazz;

    private FastClass fastClass;

    private BeanInfo beanInfo;

    private Map propertys = new ConcurrentHashMap<>();

    private Map methodProxys = new ConcurrentHashMap<>();

    private Map, Constructor> constructors = new ConcurrentHashMap<>();

    private Map fields = new ConcurrentHashMap<>();

    private Map staticFields = new ConcurrentHashMap<>();

    @SuppressWarnings("unchecked")
    public FastClasses(Class clazz) {
        this.clazz = clazz;
        this.fastClass = FastClass.create(clazz);
        if (!clazz.isInterface()) {
            this.beanInfo = ClassUtils.getBeanInfo(clazz);
            PropertyDescriptor[] propertyDescriptors = this.beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor descriptor : propertyDescriptors) {
                MethodProxy readMethodProxy = descriptor.getReadMethod() == null ? null : new MethodProxy(descriptor.getReadMethod());
                MethodProxy writeMethodProxy = descriptor.getWriteMethod() == null ? null : new MethodProxy(descriptor.getWriteMethod(), descriptor.getPropertyType());
                this.propertys.put(descriptor.getName(), new ObjectProperty(descriptor.getName(), readMethodProxy, writeMethodProxy, descriptor.getPropertyType()));
            }
            for (Method method : this.clazz.getDeclaredMethods()) {
                Class[] parameters = method.getParameterTypes();
                StringBuilder name = new StringBuilder(method.getName());
                if (parameters.length != 0) {
                    for (int i = 0; i < parameters.length; i++) {
                        Class parameterType = parameters[i];
                        name.append(i == 0 ? "(" : "");
                        name.append(parameterType.getName());
                        name.append(i + 1 == parameters.length ? ")" : ",");
                    }
                } else {
                    name.append("()");
                }
                try {
                    if (method.isAccessible()) {
                        this.methodProxys.put(name.toString(), new MethodProxy(this.fastClass.getMethod(method), parameters));
                    } else {
                        if (!method.isAccessible()) {
                            method.setAccessible(true);
                        }
                        this.methodProxys.put(name.toString(), new MethodProxy(method, parameters));
                    }
                } catch (Exception e) {
                    LOGGER.error(e.getMessage(), e);
                }
            }
            for (Constructor constructor : clazz.getConstructors()) {
                Class[] parameterTypes = constructor.getParameterTypes();
                if (parameterTypes.length == 1) {
                    this.constructors.put(parameterTypes[0], (Constructor) constructor);
                }
            }
        } else {
            for (Method method : clazz.getDeclaredMethods()) {
                StringBuilder name = new StringBuilder(method.getName());
                Class[] parameters = method.getParameterTypes();
                for (int i = 0; i < parameters.length; i++) {
                    Class parameterType = parameters[i];
                    name.append(i == 0 ? "(" : "").append(parameterType.getName()).append(i + 1 == parameters.length ? ")" : ",");
                }
                this.methodProxys.put(name.toString(), new MethodProxy(this.fastClass.getMethod(method), parameters));
            }
        }
        for (Class superClass = clazz; superClass != Object.class; ) {
            for (Field field : filterFields(superClass.getDeclaredFields())) {
                if (!this.fields.containsKey(field.getName())) {
                    this.fields.put(field.getName(), field);
                }
            }
            superClass = superClass.getSuperclass();
        }
    }

    private List filterFields(Field[] fields) {
        List result = new ArrayList<>();
        for (Field field : fields) {
            if (!Modifier.isStatic(field.getModifiers())) {
                field.setAccessible(true);
                result.add(field);
            } else {
                field.setAccessible(true);
                staticFields.put(field.getName(), field);
            }
        }
        return result;
    }

    @Override
    public T newInstance() {
        try {
            return this.clazz.newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    @Override
    public T newInstance(Object object) {
        try {
            if (object == null) {
                return newInstance();
            }
            return newInstance(object.getClass(), object);
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    @Override
    @SuppressWarnings("unchecked")
    public T newInstance(Class type, Object object) {
        try {
            return this.constructors.get(type).newInstance(new Object[]{object});
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    @Override
    public ObjectProperty getProperty(String name) {
        if (this.propertys.containsKey(name)) {
            return this.propertys.get(name);
        }
        return null;
    }

    @Override
    public ObjectProperty[] getPropertys() {
        return this.propertys.values().toArray(new ObjectProperty[this.propertys.size()]);
    }

    @Override
    public MethodProxy getMethod(String methodName) {
        MethodProxy methodProxy = this.methodProxys.get(methodName + "()");
        if (org.apache.commons.lang3.ObjectUtils.allNotNull(methodProxy)) {
            return methodProxy;
        }
        for (Map.Entry entry : this.methodProxys.entrySet()) {
            if (entry.getKey().equals(methodName) || entry.getKey().startsWith(methodName + "(")) {
                return entry.getValue();
            }
        }
        if (this.clazz.getSuperclass() != Object.class) {
            return ClassUtils.getMethodProxy(this.clazz.getSuperclass(), methodName);
        }
        return null;
    }

    @Override
    public MethodProxy getMethod(String methodName, Class... parameterTypes) {
        StringBuilder methodname = new StringBuilder(methodName);
        if (parameterTypes.length != 0) {
            for (int i = 0; i < parameterTypes.length; i++) {
                methodname.append(i == 0 ? "(" : "").append(parameterTypes[i].getName()).append(i + 1 == parameterTypes.length ? ")" : ",");
            }
        } else {
            methodname.append("()");
        }
        return this.methodProxys.get(methodname.toString());
    }

    @Override
    public void setValue(Object target, String name, Object value) {
        Field field = this.fields.get(name);
        try {
            if (field != null) {
                field.set(target, value);
            } else {
                throw new RuntimeException(String.format("没有找到[%s.%s]对应的属性!", clazz.getName(), name));
            }
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    @Override
    public  V getValue(Object target, String name) {
        try {
            return getValue(target, this.fields.get(name));
        } catch (IllegalAccessException | NoSuchFieldException ex) {
            throw new RuntimeException(String.format("没有找到[%s.%s]对应的属性!", clazz.getName(), name));
        }
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    public  V getValue(Object target, Field field) throws IllegalAccessException, NoSuchFieldException {
        if (field == null) {
            throw new NoSuchFieldException("字段不存在");
        }
        return (V) field.get(target);
    }

    @Override
    public T newInstance(Class[] parameterTypes, Object[] parameters) {
        if (parameterTypes.length == 0) {
            return newInstance();
        }
        if (parameterTypes.length == 1) {
            return newInstance(parameterTypes[0], parameters[0]);
        }
        throw new RuntimeException("还不支持多个参数的构造器");
    }

    @Override
    public Field[] getDeclaredFields() {
        return this.fields.values().toArray(new Field[this.fields.size()]);
    }

    @Override
    public Field getDeclaredField(String fieldName) {
        return this.fields.get(fieldName);
    }

    @Override
    public Field[] getDeclaredFields(Class annotClass) {
        List retvalues = new ArrayList<>();
        for (Field field : this.fields.values()) {
            if (field.isAnnotationPresent(annotClass)) {
                retvalues.add(field);
            }
        }
        return retvalues.toArray(new Field[retvalues.size()]);
    }

    @Override
    public  V getValue(String name) {
        try {
            return this.getValue(null, this.staticFields.get(name));
        } catch (IllegalAccessException | NoSuchFieldException ex) {
            throw new RuntimeException(String.format("没有找到[%s.%s]对应的属性!", clazz.getName(), name));
        }

    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy