今天看下了spring的源码,看到AbstractAutowireCapableBeanFactory类中creanbean方法自动创建bean时,用到了反射,下面就我看到的spring中package org.springframework.util 下的ReflectionUtils 和beanutils中下总结了,也和大家共同学习:
beanutils 中的copyProperties(Object source, Object target)大家一定不会陌生,apache中也用这个方法,大家也经常用,原理都是用到了反射:
private static void copyProperties(Object source, Object target, Class editable, String[] ignoreProperties) throws BeansException { Assert.notNull(source, "Source must not be null"); Assert.notNull(target, "Target must not be null"); // 我们用到的editable,ignoreProperties 一般都为空,但是我个人觉得ignoreProperties 还是挺有用的,过滤些不要的属性 Class actualEditable = target.getClass(); if (editable != null) { if (!editable.isInstance(target)) { throw new IllegalArgumentException("Target class [" + target.getClass().getName() + "] not assignable to Editable class [" + editable.getName() + "]"); } actualEditable = editable; } PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable); List ignoreList = (ignoreProperties != null) ? Arrays.asList(ignoreProperties) : null; for (int i = 0; i < targetPds.length; i++) { PropertyDescriptor targetPd = targetPds[i]; if (targetPd.getWriteMethod() != null && (ignoreProperties == null || (!ignoreList.contains(targetPd.getName())))) { PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName()); if (sourcePd != null && sourcePd.getReadMethod() != null) { try { Method readMethod = sourcePd.getReadMethod(); if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) { readMethod.setAccessible(true); } Object value = readMethod.invoke(source, new Object[0]); Method writeMethod = targetPd.getWriteMethod(); if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) { writeMethod.setAccessible(true); } writeMethod.invoke(target, new Object[] {value}); } catch (Throwable ex) { throw new FatalBeanException("Could not copy properties from source to target", ex); } } } } }
再说下PropertyDescriptor类
PropertyDescriptor类表示JavaBean类通过存储器导出一个属性。主要方法:
1、getPropertyType(),获得属性的Class对象。
2、getReadMethod(),获得用于读取属性值的方法;
getWriteMethod(),获得用于写入属性值的方法。
3、hashCode(),获取对象的哈希值。
4、setReadMethod(Method readMethod),设置用于读取属性值的方法;setWriteMethod(MethodwriteMethod),设置用于写入属性值的方法
调用其方法应优先使用java.beans.PropertyDescriptor获取Method进行方法调用,以获得更大的可维护性。
在ReflectionUtils中有很多小方法 看来简单其实是很实用的
比如在一个class查找某个属性
public static Field findField(Class clazz, String name, Class type) { Assert.notNull(clazz, "Class must not be null"); Assert.isTrue(name != null || type != null, "Either name or type of the field must be specified"); Class searchType = clazz; while (!Object.class.equals(searchType) && searchType != null) { Field[] fields = searchType.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { Field field = fields[i]; if ((name == null || name.equals(field.getName())) && (type == null || type.equals(field.getType()))) { return field; } } //查找父类的属性 searchType = searchType.getSuperclass(); } return null; }在class中查找某个方法
public static Method findMethod(Class clazz, String name, Class[] paramTypes) { Assert.notNull(clazz, "Class must not be null"); Assert.notNull(name, "Method name must not be null"); Class searchType = clazz; while (!Object.class.equals(searchType) && searchType != null) { Method[] methods = (searchType.isInterface() ? searchType.getMethods() : searchType.getDeclaredMethods()); for (int i = 0; i < methods.length; i++) { Method method = methods[i]; if (name.equals(method.getName()) && (paramTypes == null || Arrays.equals(paramTypes, method.getParameterTypes()))) { return method; } } searchType = searchType.getSuperclass(); } return null; }
某属性是否是final、static、public来修饰
public static boolean isPublicStaticFinal(Field field) { int modifiers = field.getModifiers(); return (Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)); }
标记某个数据有访问权限
public static void makeAccessible(Field field) { if (!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers())) { field.setAccessible(true); } }有一种代码的写法也在我们代码中很实用,但是我们很少这样去写,我个人认为这样写比较清晰
public static Method[] getAllDeclaredMethods(Class leafClass) throws IllegalArgumentException { final List list = new ArrayList(32); doWithMethods(leafClass, new MethodCallback() { public void doWith(Method method) { list.add(method); } }); return (Method[]) list.toArray(new Method[list.size()]); } public static interface MethodCallback { /** * Perform an operation using the given method. * @param method the method to operate on */ void doWith(Method method) throws IllegalArgumentException, IllegalAccessException; }