反射优化
要优化首先得知道瓶颈点,如下代码进行测试。
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class ReflectTest { public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { User user = new User("zhengbiyu"); long startTime = System.currentTimeMillis(); for (int i = 0; i < 1000000; i++) { user.getName(); } long endTime = System.currentTimeMillis(); System.out.println("未反射总耗时:" + (endTime - startTime) + "ms"); startTime = System.currentTimeMillis(); Method getMethod = null; for (int i = 0; i < 1000000; i++) { getMethod = User.class.getDeclaredMethod("getName"); } endTime = System.currentTimeMillis(); System.out.println("反射获取方法信息总耗时:" + (endTime - startTime) + "ms"); startTime = System.currentTimeMillis(); for (int i = 0; i < 1000000; i++) { getMethod.invoke(user); } endTime = System.currentTimeMillis(); System.out.println("反射调用方法总耗时:" + (endTime - startTime) + "ms"); } } class User { private String name; public User(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
可以看出瓶颈点在于获取方法信息。
缓存字段、方法信息
那我们可以将获取到的方法信息进行一个缓存,就不用每次获取了。mybatis框架就是这样进行优化的:
org.apache.ibatis.reflection.Reflector
/** * This class represents a cached set of class definition information that * allows for easy mapping between property names and getter/setter methods. * * @author Clinton Begin */ public class Reflector { private final Class<?> type; private final String[] readablePropertyNames; private final String[] writeablePropertyNames;
//对set、get、构造方法进行缓存 private final Map<String, Invoker> setMethods = new HashMap<String, Invoker>(); private final Map<String, Invoker> getMethods = new HashMap<String, Invoker>(); private final Map<String, Class<?>> setTypes = new HashMap<String, Class<?>>(); private final Map<String, Class<?>> getTypes = new HashMap<String, Class<?>>(); private Constructor<?> defaultConstructor; private Map<String, String> caseInsensitivePropertyMap = new HashMap<String, String>(); public Reflector(Class<?> clazz) { type = clazz; addDefaultConstructor(clazz); addGetMethods(clazz); addSetMethods(clazz); addFields(clazz); readablePropertyNames = getMethods.keySet().toArray(new String[getMethods.keySet().size()]); writeablePropertyNames = setMethods.keySet().toArray(new String[setMethods.keySet().size()]); for (String propName : readablePropertyNames) { caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName); } for (String propName : writeablePropertyNames) { caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName); } } private void addDefaultConstructor(Class<?> clazz) { Constructor<?>[] consts = clazz.getDeclaredConstructors(); for (Constructor<?> constructor : consts) { if (constructor.getParameterTypes().length == 0) { if (canAccessPrivateMethods()) { try { constructor.setAccessible(true); } catch (Exception e) { // Ignored. This is only a final precaution, nothing we can do. } } if (constructor.isAccessible()) { this.defaultConstructor = constructor; } } } } private void addGetMethods(Class<?> cls) { Map<String, List<Method>> conflictingGetters = new HashMap<String, List<Method>>(); Method[] methods = getClassMethods(cls); for (Method method : methods) { if (method.getParameterTypes().length > 0) { continue; } String name = method.getName(); if ((name.startsWith("get") && name.length() > 3) || (name.startsWith("is") && name.length() > 2)) { name = PropertyNamer.methodToProperty(name); addMethodConflict(conflictingGetters, name, method); } } resolveGetterConflicts(conflictingGetters); } }
动态生成类
通过字节码生成,生成一个类,类的方法实现是直接调用原方法。编译、加载类。
public interface ObjectFieldGetter { /** * 获取对应的param对应的filedName属性值 * * @param params * @param filedName * @return */ Object get(Object[] params, String filedName); }
生成类示例:
public class DynamicObjectFieldGetterImpl序号 implements ObjectFieldGetter { @Override public Object get(Object[] args, String filedName) { return ((com.xxx.xxx.原对象类限定名) args[0]).getPin(); } }
编译加载动态生成的类。