`
wuxing429
  • 浏览: 15514 次
  • 性别: Icon_minigender_2
  • 来自: 杭州
社区版块
存档分类
最新评论

看spring源码学反射

 
阅读更多

今天看下了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;
	}

 

 

 
 
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics