package jef.tools.reflect;
import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import javax.management.ReflectionException;
import jef.accelerator.bean.BeanAccessor;
import jef.accelerator.bean.FastBeanWrapperImpl;
import jef.common.SimpleException;
import jef.common.log.LogUtil;
import jef.tools.ArrayUtils;
import jef.tools.Assert;
import jef.tools.Exceptions;
import jef.tools.StringUtils;
public class BeanUtils {
private static Map<Class<?>, ClassFieldAccessor> ACCESSOR_CACHE = new IdentityHashMap<Class<?>, ClassFieldAccessor>(256);
/**
* 将bean的可读属性变为map 和 {@link #describe(Object)}含义相同
*
* @param obj
* 对象
* @return 对象的属性并转换为Map
* @deprecated use {@link #describe(Object)} instead.
*/
public static Map<String, Object> toMap(Object obj) {
return describe(obj);
}
/**
* 将bean的可读属性变为map(不递归)<br>
* 使用ASM快速访问器实现。只会访问 field / getter /setter俱全的完整属性。如果要访问仅有getter的属性,请用{@link #describeByGetter(Object)}
*
* @param obj
* @return 对应的Map
*/
public static Map<String, Object> describe(Object obj) {
if (obj == null)
return Collections.emptyMap();
BeanAccessor ba = FastBeanWrapperImpl.getAccessorFor(obj.getClass());
return ba.convert(obj);
}
/**
* 将bean的可读属性变为map(不递归)
* 根据方法中所有public的getter方法来访问Bean。
* @param obj
* @return
*/
public static Map<String,Object> describeByGetter(Object obj){
if (obj == null)
return Collections.emptyMap();
Map<String,Object> map=new HashMap<String,Object>();
for(Method method: obj.getClass().getMethods()) {
if(Modifier.isStatic(method.getModifiers())) {
continue;
}
if(method.getParameterTypes().length>0) {
continue;
}
String name=method.getName();
String property;
if(name.startsWith("get") && name.length()>3) {
property=StringUtils.uncapitalize(name.substring(3));
}else if(name.startsWith("is") && name.length()>2) {
if(method.getReturnType()==Boolean.class ||method.getReturnType()==boolean.class) {
property=StringUtils.uncapitalize(name.substring(2));
}else {
continue;
}
}else {
continue;
}
try {
map.put(property, method.invoke(obj));
} catch (IllegalArgumentException e) {
throw new SimpleException("Error accessing method "+ method.toString(),e);
} catch (IllegalAccessException e) {
throw new SimpleException("Error accessing method "+ method.toString(),e);
} catch (InvocationTargetException e) {
throw new SimpleException("Error accessing method "+ method.toString(),e.getTargetException());
}
}
return map;
}
/**
* 将Map转换回Bean,要求类型一致,比如Bean中的int对应Map中的Integer
*
* @param map
* Map
* @param clz
* 目标类型
*/
@SuppressWarnings("unchecked")
public static <T> T undescribe(Map<String, Object> map, Class<T> clz) {
BeanAccessor ba = FastBeanWrapperImpl.getAccessorFor(clz);
return (T) ba.fromMap(map);
}
/**
* 将Map转换回Bean,map中类型可以和Bean中数据类型不太一致,因此将花费更多的时间进行动态的类型判断和转换
*
* <br>
* @see ConvertUtils#toProperType(Object, Class) 对每个属性都将使用此方法进行类型检查和转换。
*
* @param map
* @param clz
* @return
*/
@SuppressWarnings("unchecked")
public static <T> T undescribeSafe(Map<String, Object> map, Class<T> clz) {
BeanAccessor ba = FastBeanWrapperImpl.getAccessorFor(clz);
return (T) ba.fromMap2(map);
}
/**
* 强行获取字段值 ,且不抛出受检异常(慎用)
*
* @param obj
* @param fieldName
* @return
*/
public static Object getFieldValue(Object obj, String fieldName) {
if (obj == null)
return null;
Class<?> clz = obj.getClass();
ClassFieldAccessor accessors = ACCESSOR_CACHE.get(clz);
if (accessors == null) {
accessors = new ClassFieldAccessor();
ACCESSOR_CACHE = copyOnWritePut(clz, accessors, ACCESSOR_CACHE);
} else {
FieldAccessor acc = accessors.get(fieldName);
if (acc != null) {
return acc.getObject(obj);
}
}
FieldEx f = getField(clz, fieldName);
if (f == null)
throw new NoSuchElementException(fieldName + " in " + clz.getName());
accessors.put(fieldName, f.getAccessor());
return f.get(obj);
}
/**
* get the field accessor.
*
* @param field
* field
* @param cache
* if true, the result accessor will be cached.
* @return
*/
public static FieldAccessor getFieldAccessor(java.lang.reflect.Field field, boolean cache) {
Class<?> clz = field.getDeclaringClass();
FieldAccessor accessor = null;
ClassFieldAccessor accessors = ACCESSOR_CACHE.get(clz);
if (accessors != null) {
accessor = accessors.get(field.getName());
}
if (accessor == null) {
accessor = FieldAccessor.generateAccessor(field);
}
if (cache) {
if (accessors == null) {
accessors = new ClassFieldAccessor();
ACCESSOR_CACHE = copyOnWritePut(clz, accessors, ACCESSOR_CACHE);
}
accessors.put(field.getName(), accessor);
}
return accessor;
}
/**
* 获取指定的Field的类型
*
* @param clz
* 类
* @param fieldName
* 字段名
* @return 字段类型
*
*/
public static Class<?> getFieldType(Class<?> clz, String fieldName) {
ClassFieldAccessor accessors = ACCESSOR_CACHE.get(clz);
if (accessors == null) {
accessors = new ClassFieldAccessor();
ACCESSOR_CACHE = copyOnWritePut(clz, accessors, ACCESSOR_CACHE);
} else {
FieldAccessor acc = accessors.get(fieldName);
if (acc != null) {
return acc.getType();
}
}
FieldEx f = getField(clz, fieldName);
if (f == null)
throw new NoSuchElementException(fieldName + " in " + clz.getName());
accessors.put(fieldName, f.getAccessor());
return f.getType();
}
private static <K, V> Map<K, V> copyOnWritePut(K k, V v, Map<K, V> source) {
Map<K, V> map = new IdentityHashMap<K, V>(source);
map.put(k, v);
return map;
}
/**
* 强行设置字段值
*
* @param obj
* 目标对象
* @param fieldName
* 字段名
* @param value
* 字段值
*/
public static void setFieldValue(Object obj, String fieldName, Object value) {
if (obj == null)
return;
Class<?> clz = obj.getClass();
ClassFieldAccessor accessors = ACCESSOR_CACHE.get(clz);
if (accessors == null) {
accessors = new ClassFieldAccessor();
ACCESSOR_CACHE = copyOnWritePut(clz, accessors, ACCESSOR_CACHE);
} else {
FieldAccessor acc = accessors.get(fieldName);
if (acc != null) {
acc.set(obj, value);
return;
}
}
FieldEx f = getField(obj.getClass(), fieldName);
if (f == null)
throw new NoSuchElementException(fieldName + " in " + clz.getName());
accessors.put(fieldName, f.getAccessor());
f.set(obj, value);
}
/**
* 获取指定的Field <li>Class.getField不会返回受保护的和私有的方法,getDeclaredField不会返回父类中的方法。
* 此处可以返回受保护的和私有的方法(并可以运行)。子类中没有的也会去父类中找。</li>
*
* @param cls
* 类
* @param fieldName
* 字段名
* @return 该字段对象
* @see FieldEx
*/
public static FieldEx getField(Class<?> cls, String fieldName) {
return getField(new ClassEx(cls), fieldName);
}
/**
* 获取指定的Field
*
* @Title: getField
*/
static FieldEx getField(ClassEx c, String name) {
java.lang.reflect.Field f = null;
Class<?> cls = c.getWrappered();
while (cls != null) {
try {
f = cls.getDeclaredField(name);
} catch (SecurityException e) {
LogUtil.exception(e);
} catch (NoSuchFieldException e) {
// do nothing
}
if (f != null)
break;
cls = cls.getSuperclass();
}
if (f == null)
return null;
return new FieldEx(f, c);
}
/**
* 用String设置字段的值
*
* @param obj
* 对象
* @param fieldName
* 字段名
* @param value
* 值的String表达
*/
public static boolean setFieldValueByString(Object obj, String fieldName, String value) throws ReflectionException {
if (obj == null)
return false;
FieldEx f = getField(obj.getClass(), fieldName);
if (f == null)
return false;
Type c = f.getGenericType();
try {
Object oldValue = f.get(obj);
Object objV = ConvertUtils.toProperType(value, new ClassEx(c), oldValue);
f.set(obj, objV);
} catch (IllegalArgumentException e) {
LogUtil.error("Error processing:" + fieldName);
LogUtil.exception(e);
throw new ReflectionException(e, e.getMessage());
}
return true;
}
/**
* 使用空参数构造,无视构造参数一律传null
*/
public static Object newInstanceAnyway(Class<?> cls) throws ReflectionException {
Constructor<?> c = null;
Object o = ConvertUtils.defaultValueForBasicType(cls);
if (o != null)
return null;
for (Constructor<?> con : cls.getDeclaredConstructors()) {// 获取全部构造
if (c == null) {
c = con;
} else if (c.getParameterTypes().length > con.getParameterTypes().length) {// 取参数较少的构造
c = con;
}
if (c.getParameterTypes().length == 0) {// 如果已经有参数为0的,就不再循环
break;
}
}
if (c == null)
return null;
if (!Modifier.isPublic(c.getModifiers())) {
try {
c.setAccessible(true);
} catch (SecurityException e) {
LogUtil.exception(c.getName(), e);
}
}
Class<?>[] types = c.getParameterTypes();
Object[] p = new Object[types.length];
for (int i = 0; i < types.length; i++) {
// modified by mjj,2011.9.30
p[i] = ConvertUtils.defaultValueForBasicType(types[i]);
}
try {
return c.newInstance(p);
} catch (Exception e) {
LogUtil.exception(e);
return null;
}
}
/**
* 包装类转换为原生类
*
* @param wrapperClass
* @return
*/
public static Class<?> toPrimitiveClass(Class<?> wrapperClass) {
if (wrapperClass == Integer.class) {
return Integer.TYPE;
} else if (wrapperClass == Byte.class) {
return Byte.TYPE;
} else if (wrapperClass == Short.class) {
return Short.TYPE;
} else if (wrapperClass == Long.class) {
return Long.TYPE;
} else if (wrapperClass == Float.class) {
return Float.TYPE;
} else if (wrapperClass == Double.class) {
return Double.TYPE;
} else if (wrapperClass == Character.class) {
return Character.TYPE;
} else if (wrapperClass == Boolean.class) {
return Boolean.TYPE;
} else {
return wrapperClass;
}
}
/**
* 将8原生类型的类转换为对应的包装的类型。
*/
public static Class<?> toWrapperClass(Class<?> primitiveClass) {
if (primitiveClass == Integer.TYPE)
return Integer.class;
if (primitiveClass == Long.TYPE)
return Long.class;
if (primitiveClass == Double.TYPE)
return Double.class;
if (primitiveClass == Short.TYPE)
return Short.class;
if (primitiveClass == Float.TYPE)
return Float.class;
if (primitiveClass == Character.TYPE)
return Character.class;
if (primitiveClass == Byte.TYPE)
return Byte.class;
if (primitiveClass == Boolean.TYPE)
return Boolean.class;
return primitiveClass;
}
/**
* 得到所有的字段名称
*
* @param cls
* @param resolveUntilSuperclass
* @return
*/
public static String[] getFieldNames(Class<?> cls, Class<?> resolveUntilSuperclass) {
FieldEx[] fields = getFields(cls, resolveUntilSuperclass, false, false);
String[] result = new String[fields.length];
for (int i = 0; i < fields.length; i++) {
result[i] = fields[i].getName();
}
return result;
}
public static FieldEx[] getFields(Class<?> c) {
return getFields(c, true);
}
public static FieldEx[] getFields(Class<?> c, boolean resolveSuper) {
return getFields(c, resolveSuper ? Object.class : null, false, false);
}
public static FieldEx[] getFieldsWithGetterAndSetter(Class<?> cls, Class<?> resolveUntilSuperclass) {
return getFields(cls, resolveUntilSuperclass, true, true);
}
public static FieldEx[] getFieldsWithGetter(Class<?> cls, Class<Object> resolveUntilSuperclass) {
return getFields(cls, resolveUntilSuperclass, true, false);
}
public static FieldEx[] getFieldsWithSetter(Class<?> cls, Class<Object> resolveUntilSuperclass) {
return getFields(cls, resolveUntilSuperclass, false, true);
}
/**
* 获取一个类中的全部字段。
*
* @param c
* @param resolveUntilSuperclass
* : 解析父类,直到出现指定的类型,为null,表示不解析父类
* @return
*/
public static FieldEx[] getFields(Class<?> c, Class<?> resolveUntilSuperclass, boolean mustWithGetter, boolean mustWithSetter) {
if (resolveUntilSuperclass == null) {
resolveUntilSuperclass = c.getSuperclass();
}
List<FieldEx> fields = new ArrayList<FieldEx>();
HashSet<String> names = new HashSet<String>();
ClassEx context = new ClassEx(c);
Class<?> cls = c;
while (cls != resolveUntilSuperclass) {
for (Field field : cls.getDeclaredFields()) {
int mod = field.getModifiers();
if (Modifier.isStatic(mod) || Modifier.isNative(mod)) {
continue;
}
if (names.contains(field.getName()))
continue;// 如果父类中有和子类同名的字段,则跳过(被子类覆盖)
FieldEx fex = new FieldEx(field, context);
if (mustWithGetter) {
MethodEx getter = getGetter(fex);
if (getter == null)
continue;
}
if (mustWithSetter) {
MethodEx setter = getSetter(fex);
if (setter == null)
continue;
}
names.add(field.getName());
fields.add(fex);
if (!Modifier.isPublic(field.getModifiers())) {
try {
field.setAccessible(true);
} catch (SecurityException e) {
System.out.println(field.toString() + "\n" + e.getMessage());
}
}
}
cls = cls.getSuperclass();
}
return fields.toArray(new FieldEx[fields.size()]);
}
/**
* 判断Field在其所定义的类当中是否有默认的getter和setter
*
* @param field
* @return
*/
public static boolean hasGetterAndSetter(FieldEx field) {
MethodEx getter = getGetter(field);
MethodEx setter = getSetter(field);
return getter != null && setter != null;
}
/**
* 根据类的名称和参数构造实例。 如果不能创建则返回null;
*
* @param className
* 类名
* @param params
* 构造参数
* @return 实例。如果过程中出现错误返回null。(不抛出异常)
*/
public static Object newInstance(String className, Object... params) {
Class<?> clz;
try {
clz = Class.forName(className);
return newInstance(clz, params);
} catch (ClassNotFoundException e) {
return null;
}
}
/**
* 待参数调用构造方法来创建实例
*
* @param cls
* 类
* @param params
* 构造参数
* @return 实例
*/
@SuppressWarnings("unchecked")
public static <T> T newInstance(Class<T> cls, Object... params) {
Constructor<T> me = null;
if (params.length == 0) {
try {
me = cls.getDeclaredConstructor();
if (me != null) {
if (!Modifier.isPublic(me.getModifiers())) {
me.setAccessible(true);
}
return me.newInstance(params);
}
} catch (Exception e) {
Exceptions.thorwAsIllegalState(e);
}
}
List<Class<?>> list = new ArrayList<Class<?>>();
for (Object pobj : params) {
list.add(pobj.getClass());
}
Class<?>[] inputTypes = list.toArray(new Class[list.size()]);
for (Constructor<?> ct : cls.getDeclaredConstructors()) {
if (ct.getParameterTypes().length == list.size()) {
if (isParameterCompatible(ct.getParameterTypes(), inputTypes, ct.isVarArgs())) {
if (!Modifier.isPublic(ct.getModifiers())) {
try {
ct.setAccessible(true);
} catch (SecurityException e) {
System.out.println(ct.toString() + "\n" + e.getMessage());
}
}
try {
return (T) ct.newInstance(params);
} catch (IllegalArgumentException e) {
LogUtil.exception(e);
} catch (InstantiationException e) {
LogUtil.exception(e);
} catch (IllegalAccessException e) {
LogUtil.exception(e);
} catch (InvocationTargetException e) {
LogUtil.exception(e);
}
}
}
}
return null;
}
/**
* 给定方法参数类型和 值参数类型,比较值类型是否可以作为该方法的参数。
*
* @param methodTypes
* @param inputTypes
* @return
*/
public static boolean isParameterCompatible(Class<?>[] methodTypes, Class<?>[] inputTypes, boolean varArg) {
if (varArg && methodTypes.length == inputTypes.length - 1) {// 如果是可变参数就加上最后一个参数
inputTypes = ArrayUtils.addElement(inputTypes, methodTypes[methodTypes.length - 1]);
}
if (methodTypes.length != inputTypes.length)
return false;
for (int i = 0; i < methodTypes.length; i++) {// 检测每一个参数的类型是否匹配
if (inputTypes[i] == null)
continue;
if (methodTypes[i].isPrimitive()) { // 如果方法的参数类型 是 原生类型,则包装
methodTypes[i] = BeanUtils.toWrapperClass(methodTypes[i]);
}
if (inputTypes[i].isPrimitive()) { // 如果输入参数类型 是 原生类型,则包装
inputTypes[i] = BeanUtils.toWrapperClass(inputTypes[i]);
}
if (!methodTypes[i].isAssignableFrom(inputTypes[i])) {
return false;
}
}
return true;
}
/**
* 获取所有方法:
*
* @param cls
* @return
*/
public static MethodEx[] getMethods(Class<?> cls) {
Method[] methods = cls.getMethods();
ClassEx cw = new ClassEx(cls);
MethodEx[] result = new MethodEx[methods.length];
for (int i = 0; i < methods.length; i++) {
result[i] = new MethodEx(methods[i], cw);
}
return result;
}
/**
* 返回符合参数的方法,和jdk的Class.getMethod(String name, Class...
* parameterTypes)有以下区别: <li>
* Class.getMethod不会返回受保护的和私有的方法,getDeclaredMethod不会返回父类中的方法。
* 此处可以返回受保护的和私有的方法(并可以运行)。子类中没有的也会去父类中找。</li> <li>
* Class.getMethod要求paramTypes完全一致才会返回方法,此处只要paramTypes兼容,即可返回。
* (例如:方法输入参数为Object,JDK默认要求你用Object.class作为参数才能得到方法,此处你可以用Object的任意子类来得到方法)
* </li> <li>此处的方法允许输入参数中的某个Class为null,表示放弃对该参数的兼容性检查。</li>
*
* @param c
* @param method
* @param paramTypes
* @return
*/
public static MethodEx getCompatibleMethod(Class<?> c, String method, Class<?>... paramTypes) {
Method m = null;
Class<?> su = c;
while (su != null) {
m = getDeclaredMethod(su, method, paramTypes);
if (m != null)
break;
if (su.isInterface()) {
Class<?>[] clz = su.getInterfaces();
if (clz.length > 0) {
su = clz[0];
} else {
su = null;
}
} else {
su = su.getSuperclass();
}
}
if (m != null && !Modifier.isPublic(m.getModifiers())) {
try {
m.setAccessible(true);
} catch (SecurityException e) {
System.out.println(m.toString() + "\n" + e.getMessage());
}
}
if (m == null)
return null;
return new MethodEx(m, c);
}
/**
* 根据方法名和参数从类中获得方法
*
*
*/
private static Method getDeclaredMethod(Class<?> su, String method, Class<?>... paramTypes) {
try {
for (Method m : su.getDeclaredMethods()) {
if (!m.getName().equals(method))
continue;
Class<?>[] types = m.getParameterTypes();
if (BeanUtils.isParameterCompatible(types, paramTypes, m.isVarArgs()))
return m;
}
} catch (SecurityException e) {
LogUtil.exception(e);
}
return null;
}
/**
* 返回有所符合名称的方法
*
* @param c
* 类
* @param name
* 方法名
* @param maxReturn
* 最多返回的方法数,设置较少的数量有利于减少循环次数。
* @return
*/
public static MethodEx[] getMethodByName(ClassEx c, String name, int maxReturn) {
return getMethodByName(c, name, maxReturn, SearchMode.ALLWAYS_IN_SUPER);
}
public enum SearchMode {
/**
* 永远不查找父类
*/
NOT_IN_SUPER,
/**
* 即便查找数量不满足,但是只要找到了(>0),就不查找父类
*/
NOT_IN_SUPER_IF_FOUND,
/**
* 无论如何都要查找父类
*/
ALLWAYS_IN_SUPER
}
/**
* 返回有所符合名称的方法
*
* @param c
* @param name
* @param maxReturn
* 最多返回
* @param mode
* 当找不到时,继续查找父类的方法,行为特征
* @return
*/
public static MethodEx[] getMethodByName(ClassEx c, String name, int maxReturn, SearchMode mode) {
List<MethodEx> methods = new ArrayList<MethodEx>();
HashSet<String> resultNames = new HashSet<String>();
Class<?> su = c.getWrappered();
while (su != Object.class) {
for (Method m : su.getDeclaredMethods()) {
if (!m.getName().equals(name)) {// 名称不等则跳过
continue;
}
Method bridgeMethod = null;
if (m.isBridge()) {
bridgeMethod = m;
m = BridgeMethodResolver.findBridgedMethod(m);
// 桥接
} else {
// 非橋接計算的方法必須讓位給橋接計算的方法
if (resultNames.contains(m.toString())) {
continue;
}
}
resultNames.add(m.toString());
MethodEx mex = new MethodEx(m, c);
mex.setBridgeMethod(bridgeMethod);
if (methods.contains(mex)) {
methods.remove(mex);
}
methods.add(mex);
}
if (maxReturn > 0 && methods.size() >= maxReturn) {// 数量满足则返回
break;
}
if (methods.size() > 0 && mode == SearchMode.NOT_IN_SUPER_IF_FOUND) {
break;
} else if (mode == SearchMode.NOT_IN_SUPER) {
break;
}
su = su.getSuperclass();
}
for (MethodEx m : methods) {
if (m != null && !Modifier.isPublic(m.getModifiers())) {
try {
m.setAccessible(true);
} catch (SecurityException e) {
System.out.println(m.toString() + "\n" + e.getMessage());
}
}
}
return methods.toArray(new MethodEx[methods.size()]);
}
/**
* 针对已经构造好的对象,执行这个方法
*
* @param obj
* 目标对象
* @param method
* 方法名
* @param params
* 方法参数
* @return 调用结果
* @throws ReflectionException
*/
public static Object invokeMethod(Object obj, String method, Object... params) throws ReflectionException {
ClassEx r = new ClassEx(obj.getClass());
return r.innerInvoke(obj, method, false, params);
}
/**
* 反射调用静态方法
*
* @param clz
* 目标类
* @param method
* 目标方法
* @param params
* 传入参数
* @return 调用结果
* @throws ReflectionException
* 反射异常
*/
@SuppressWarnings("unchecked")
public static <X> X invokeStatic(Class<?> clz, String method, Object... params) throws ReflectionException {
ClassEx r = new ClassEx(clz);
return (X) r.invokeStaticMethod(method, params);
}
/**
* 从集合对象bean中的每个元素都获取一个字段的值,并且将这些值组成数组返回
*
* @param entities
* @param fieldName
* @param type
* @return
*/
public static <T> T[] getFieldValues(Collection<?> entities, String fieldName, Class<T> type) {
return getFieldValues(entities, fieldName, type, true);
}
/**
* 从集合对象bean中的每个元素都获取一个字段的值,并且将这些值组成数组返回
*
* @param entities
* 对象集合
* @param fieldName
* 字段名(支持复杂语法,如. [n]等表示嵌套元素或者数组下标)
* @param type
* @param ignoreNullElement
* 如果为true,出现null元素则跳过,否则在返回结果中插入null值。
* @return
*/
@SuppressWarnings("unchecked")
public static <T> T[] getFieldValues(Collection<?> entities, String fieldName, Class<T> type, boolean ignoreNullElement) {
Assert.notNull(type, "the input class cann't be null.");
List<T> result = new ArrayList<T>(entities.size());
if (fieldName.indexOf('.') > -1 || fieldName.indexOf("[") > -1) {
for (Object e : entities) {
if (e == null) {
if (!ignoreNullElement) {
result.add(null);
}
continue;
}
BeanWrapperImpl bw = new BeanWrapperImpl(e);
result.add((T) bw.getNestedProperty(fieldName));
}
} else {
for (Object e : entities) {
if (e == null) {
if (!ignoreNullElement) {
result.add(null);
}
continue;
}
BeanAccessor ba = FastBeanWrapperImpl.getAccessorFor(e.getClass());
result.add((T) ba.getProperty(e, fieldName));
}
}
return result.toArray((T[]) Array.newInstance(type, result.size()));
}
/**
* 获取一个 public的,非Native非static指定名称的方法(非Declared模式:找父类,不找私有)
*
* @param c
* 类
* @param name
* 方法名
* @param types
* 方法类型参数
* @return
*/
static Method getNonStaticNativeMethod(Class<?> c, String name, Class<?>... types) {
try {
Method method = c.getMethod(name, types);
int mod = method.getModifiers();
if (Modifier.isStatic(mod) || Modifier.isNative(mod)) {
return null;
}
return method;
} catch (SecurityException e) {
LogUtil.exception(e);
} catch (NoSuchMethodException e) {
}
return null;
}
/**
* 获取一个非Native非static指定名称的方法(Declared模式:不找父类,可找私有)
*
* @param c
* 类
* @param name
* 方法名
* @param types
* 方法参数类型
* @return
*/
static Method getNonStaticNativeDeclaredMethod(Class<?> c, String name, Class<?>... types) {
try {
Method method = c.getDeclaredMethod(name, types);
int mod = method.getModifiers();
if (Modifier.isStatic(mod) || Modifier.isNative(mod)) {
return null;
}
if (!Modifier.isPublic(method.getModifiers())) {
method.setAccessible(true);
}
return method;
} catch (SecurityException e) {
LogUtil.exception(e);
} catch (NoSuchMethodException e) {
}
return null;
}
/**
* 获取一个非Native非static指定名称的方法(高级模式:可找私有,可找父类)
*
* @param c
* 要查找的类
* @param name
* 方法名
* @param types
* 方法参数类型
* @return
*/
static Method getNonStaticNativeDeclaredMethodWithSuperClz(Class<?> c, String name, Class<?>... types) {
do {
Method result = getNonStaticNativeDeclaredMethod(c, name, types);
if (result != null)
return result;
c = c.getSuperclass();
} while (c != null);
return null;
}
/**
* 将字段名变为大写或小写。根据Java Beans规范,有一种特殊情况。<br>
* 首字母小写但第二个字母大写时,property名称不变。
*
* @param fieldName
* @return
*/
public static String capitalizeFieldName(String fieldName) {
if (fieldName.length() > 1 && Character.isLowerCase(fieldName.charAt(0)) && Character.isUpperCase(fieldName.charAt(1))) {
return fieldName;
} else {
return StringUtils.capitalize(fieldName);
}
}
/**
* 获取field对应的getter
*
* @param field
* @return Getter方法
*/
public static MethodEx getGetter(FieldEx field) {
Class<?> c = field.getDeclaringClass();
Class<?> type = field.getDeclaringType();
Method getter = getNonStaticNativeDeclaredMethodWithSuperClz(c, "get" + capitalizeFieldName(field.getName()));
if (getter == null && (type == Boolean.class || type == Boolean.TYPE)) {
if (field.getName().startsWith("is")) {
getter = getNonStaticNativeDeclaredMethodWithSuperClz(c, field.getName());
} else {
getter = getNonStaticNativeDeclaredMethodWithSuperClz(c, "is" + capitalizeFieldName(field.getName()));
}
}
if (getter == null)
return null;
return new MethodEx(getter, field.instanceClass);
}
/**
* 获得field的setter方法
*
* @param field
* field对象
* @return Setter方法。
* @see MethodEx
* @see FieldEX
*/
public static MethodEx getSetter(FieldEx field) {
Class<?> c = field.getDeclaringClass();
Class<?> type = field.getDeclaringType();
Method setter = getNonStaticNativeDeclaredMethodWithSuperClz(c, "set".concat(capitalizeFieldName(field.getName())), type);
if (setter == null && field.getName().startsWith("is") && (type == Boolean.class || type == Boolean.TYPE)) {
setter = getNonStaticNativeDeclaredMethodWithSuperClz(c, "set".concat(capitalizeFieldName(StringUtils.substringAfter(field.getName(), "is"))), type);
}
if (setter == null)
return null;
return new MethodEx(setter, field.instanceClass);
}
/**
* 获得位于方法的参数上的Annotation,
*
* @param method
* 方法
* @param i
* 参数序号,从0开始
* @param annotationClz
* 注解类的类型
* @return
*/
@SuppressWarnings("unchecked")
public static <T extends Annotation> T getParamAnnotation(Method method, int i, Class<T> annotationClz) {
Annotation[][] annos = method.getParameterAnnotations();
if (i >= annos.length) {
throw new IllegalArgumentException("the param max index is:" + annos.length + ". the input index " + i + " is out of bound.");
}
Annotation[] anns = annos[i];
if (anns == null || anns.length == 0) {
return null;
}
for (Annotation a : anns) {
if (ArrayUtils.contains(a.getClass().getInterfaces(), annotationClz)) {
return (T) a;
}
}
return null;
}
/**
* 在两个bean之间复制属性。
* <p>
* 使用了动态类技术,将为拷贝的两个对象生成一个专门的动态拷贝类,性能达到反射极限。
* <p>
* 注意:这个方法使用了BeanAccessor,如果有批量的Bean需要拷贝,使用BeanAccessor性能更好(
* 超过CGLib的BeanCopier,不过功能没有其强大),具体代码如下 <code><pre>
* BeanAccessor accessor=FastBeanWrapperImpl.getAccessorFor(source.getClass());
* accessor.copy(source,target); //循环中调用
* </pre></code>
*
* @param source
* 源对象
* @param target
* 目标对象,必须是source的子类
*/
public final static void copyProperties(Object source, Object target) {
Assert.notNull(source);
if (target == null)
return;
BeanAccessor accessor = FastBeanWrapperImpl.getAccessorFor(source.getClass());
if (source.getClass() == target.getClass() || source.getClass().isAssignableFrom(target.getClass())) {// 这个校验的性能有点差
accessor.copy(source, target);
} else {
for (String s : accessor.getPropertyNames()) {
accessor.setProperty(target, s, accessor.getProperty(source, s));
}
}
}
/**
* 将Map的数据封装为一个Annotation(使用代理实现)
*
* @param type
* Annotation类型
* @param data
* Annotation的数据。
* @return Annotation对象
*/
@SuppressWarnings("unchecked")
public static final <T extends Annotation> T asAnnotation(Class<T> type, Map<String, Object> data) {
for (Method method : type.getMethods()) {
if (method.getDeclaringClass() != type) {
continue;
}
// 如果Map中缺少数据,则用注解的默认值补上。
Object value = data.get(method.getName());
if (value == null) {
data.put(method.getName(), method.getDefaultValue());
}
}
// 创建代理。
return (T) Proxy.newProxyInstance(type.getClassLoader(), new Class<?>[] { type }, new AnnotationInvocationHandler(type, data));
}
/**
* 将文本转换为需要的类型
* @param value 文本
* @param c
* @param oldValue
* @return
* @deprecated use {@link ConvertUtils#toProperType(String, ClassEx, Object)} instead.
*/
public static Object toProperType(String value, ClassEx c, Object oldValue) {
return ConvertUtils.toProperType(value, c, oldValue);
}
}