package org.springframework.beans; import java.beans.PropertyDescriptor; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Arrays; import java.util.List; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; /** * Static convenience methods for JavaBeans: for instantiating beans, * checking bean property types, copying bean properties, etc. * * <p>Mainly for use within the framework, but to some degree also * useful for application classes. * * @author Rod Johnson * @author Juergen Hoeller * @author Rob Harrop */ public abstract class BeanUtils { /** * Convenience method to instantiate a class using its no-arg constructor. * As this method doesn't try to load classes by name, it should avoid * class-loading issues. * <p>Note that this method tries to set the constructor accessible * if given a non-accessible (that is, non-public) constructor. * @param clazz class to instantiate * @return the new instance * @throws BeanInstantiationException if the bean cannot be instantiated */ public static Object instantiateClass(Class clazz) throws BeanInstantiationException { Assert.notNull(clazz, "Class must not be null"); if (clazz.isInterface()) { throw new BeanInstantiationException(clazz, "Specified class is an interface"); } try { return instantiateClass(clazz.getDeclaredConstructor((Class[]) null), null); } catch (NoSuchMethodException ex) { throw new BeanInstantiationException(clazz, "No default constructor found", ex); } } /** * Convenience method to instantiate a class using the given constructor. * As this method doesn't try to load classes by name, it should avoid * class-loading issues. * <p>Note that this method tries to set the constructor accessible * if given a non-accessible (that is, non-public) constructor. * @param ctor the constructor to instantiate * @param args the constructor arguments to apply * @return the new instance * @throws BeanInstantiationException if the bean cannot be instantiated */ public static Object instantiateClass(Constructor ctor, Object[] args) throws BeanInstantiationException { Assert.notNull(ctor, "Constructor must not be null"); try { if (!Modifier.isPublic(ctor.getModifiers()) || !Modifier.isPublic(ctor.getDeclaringClass().getModifiers())) { ctor.setAccessible(true); } return ctor.newInstance(args); } catch (InstantiationException ex) { throw new BeanInstantiationException(ctor.getDeclaringClass(), "Is it an abstract class?", ex); } catch (IllegalAccessException ex) { throw new BeanInstantiationException(ctor.getDeclaringClass(), "Has the class definition changed? Is the constructor accessible?", ex); } catch (IllegalArgumentException ex) { throw new BeanInstantiationException(ctor.getDeclaringClass(), "Illegal arguments for constructor", ex); } catch (InvocationTargetException ex) { throw new BeanInstantiationException(ctor.getDeclaringClass(), "Constructor threw exception", ex.getTargetException()); } } /** * Find a method with the given method name and the given parameter types, * declared on the given class or one of its superclasses. Prefers public methods, * but will return a protected, package access, or private method too. * <p>Checks <code>Class.getMethod</code> first, falling back to * <code>findDeclaredMethod</code>. This allows to find public methods * without issues even in environments with restricted Java security settings. * @param clazz the class to check * @param methodName the name of the method to find * @param paramTypes the parameter types of the method to find * @return the Method object, or <code>null</code> if not found * @see java.lang.Class#getMethod * @see #findDeclaredMethod */ public static Method findMethod(Class clazz, String methodName, Class[] paramTypes) { try { return clazz.getMethod(methodName, paramTypes); } catch (NoSuchMethodException ex) { return findDeclaredMethod(clazz, methodName, paramTypes); } } /** * Find a method with the given method name and the given parameter types, * declared on the given class or one of its superclasses. Will return a public, * protected, package access, or private method. * <p>Checks <code>Class.getDeclaredMethod</code>, cascading upwards to all superclasses. * @param clazz the class to check * @param methodName the name of the method to find * @param paramTypes the parameter types of the method to find * @return the Method object, or <code>null</code> if not found * @see java.lang.Class#getDeclaredMethod */ public static Method findDeclaredMethod(Class clazz, String methodName, Class[] paramTypes) { try { return clazz.getDeclaredMethod(methodName, paramTypes); } catch (NoSuchMethodException ex) { if (clazz.getSuperclass() != null) { return findDeclaredMethod(clazz.getSuperclass(), methodName, paramTypes); } return null; } } /** * Find a method with the given method name and minimal parameters (best case: none), * declared on the given class or one of its superclasses. Prefers public methods, * but will return a protected, package access, or private method too. * <p>Checks <code>Class.getMethods</code> first, falling back to * <code>findDeclaredMethodWithMinimalParameters</code>. This allows to find public * methods without issues even in environments with restricted Java security settings. * @param clazz the class to check * @param methodName the name of the method to find * @return the Method object, or <code>null</code> if not found * @throws IllegalArgumentException if methods of the given name were found but * could not be resolved to a unique method with minimal parameters * @see java.lang.Class#getMethods * @see #findDeclaredMethodWithMinimalParameters */ public static Method findMethodWithMinimalParameters(Class clazz, String methodName) throws IllegalArgumentException { Method targetMethod = doFindMethodWithMinimalParameters(clazz.getDeclaredMethods(), methodName); if (targetMethod == null) { return findDeclaredMethodWithMinimalParameters(clazz, methodName); } return targetMethod; } /** * Find a method with the given method name and minimal parameters (best case: none), * declared on the given class or one of its superclasses. Will return a public, * protected, package access, or private method. * <p>Checks <code>Class.getDeclaredMethods</code>, cascading upwards to all superclasses. * @param clazz the class to check * @param methodName the name of the method to find * @return the Method object, or <code>null</code> if not found * @throws IllegalArgumentException if methods of the given name were found but * could not be resolved to a unique method with minimal parameters * @see java.lang.Class#getDeclaredMethods */ public static Method findDeclaredMethodWithMinimalParameters(Class clazz, String methodName) throws IllegalArgumentException { Method targetMethod = doFindMethodWithMinimalParameters(clazz.getDeclaredMethods(), methodName); if (targetMethod == null && clazz.getSuperclass() != null) { return findDeclaredMethodWithMinimalParameters(clazz.getSuperclass(), methodName); } return targetMethod; } /** * Find a method with the given method name and minimal parameters (best case: none) * in the given list of methods. * @param methods the methods to check * @param methodName the name of the method to find * @return the Method object, or <code>null</code> if not found * @throws IllegalArgumentException if methods of the given name were found but * could not be resolved to a unique method with minimal parameters */ private static Method doFindMethodWithMinimalParameters(Method[] methods, String methodName) throws IllegalArgumentException { Method targetMethod = null; int numMethodsFoundWithCurrentMinimumArgs = 0; for (int i = 0; i < methods.length; i++) { if (methods[i].getName().equals(methodName)) { int numParams = methods[i].getParameterTypes().length; if (targetMethod == null || numParams < targetMethod.getParameterTypes().length) { targetMethod = methods[i]; numMethodsFoundWithCurrentMinimumArgs = 1; } else { if (targetMethod.getParameterTypes().length == numParams) { // Additional candidate with same length. numMethodsFoundWithCurrentMinimumArgs++; } } } } if (numMethodsFoundWithCurrentMinimumArgs > 1) { throw new IllegalArgumentException("Cannot resolve method '" + methodName + "' to a unique method. Attempted to resolve to overloaded method with " + "the least number of parameters, but there were " + numMethodsFoundWithCurrentMinimumArgs + " candidates."); } return targetMethod; } /** * Parse a method signature in the form <code>methodName[([arg_list])]</code>, * where <code>arg_list</code> is an optional, comma-separated list of fully-qualified * type names, and attempts to resolve that signature against the supplied <code>Class</code>. * <p>When not supplying an argument list (<code>methodName</code>) the method whose name * matches and has the least number of parameters will be returned. When supplying an * argument type list, only the method whose name and argument types match will be returned. * <p>Note then that <code>methodName</code> and <code>methodName()</code> are <strong>not</strong> * resolved in the same way. The signature <code>methodName</code> means the method called * <code>methodName</code> with the least number of arguments, whereas <code>methodName()</code> * means the method called <code>methodName</code> with exactly 0 arguments. * <p>If no method can be found, then <code>null</code> is returned. * @param signature the method signature as String representation * @param clazz the class to resolve the method signature against * @return the resolved Method * @see #findMethod * @see #findMethodWithMinimalParameters */ public static Method resolveSignature(String signature, Class clazz) { Assert.hasText(signature, "'signature' must not be empty"); Assert.notNull(clazz, "Class must not be null"); int firstParen = signature.indexOf("("); int lastParen = signature.indexOf(")"); if (firstParen > -1 && lastParen == -1) { throw new IllegalArgumentException("Invalid method signature '" + signature + "': expected closing ')' for args list"); } else if (lastParen > -1 && firstParen == -1) { throw new IllegalArgumentException("Invalid method signature '" + signature + "': expected opening '(' for args list"); } else if (firstParen == -1 && lastParen == -1) { return findMethodWithMinimalParameters(clazz, signature); } else { String methodName = signature.substring(0, firstParen); String[] parameterTypeNames = StringUtils.commaDelimitedListToStringArray(signature.substring(firstParen + 1, lastParen)); Class[] parameterTypes = new Class[parameterTypeNames.length]; for (int i = 0; i < parameterTypeNames.length; i++) { String parameterTypeName = parameterTypeNames[i].trim(); try { parameterTypes[i] = ClassUtils.forName(parameterTypeName, clazz.getClassLoader()); } catch (Throwable ex) { throw new IllegalArgumentException("Invalid method signature: unable to resolve type [" + parameterTypeName + "] for argument " + i + ". Root cause: " + ex); } } return findMethod(clazz, methodName, parameterTypes); } } /** * Retrieve the JavaBeans <code>PropertyDescriptor</code>s of a given class. * @param clazz the Class to retrieve the PropertyDescriptors for * @return an array of <code>PropertyDescriptors</code> for the given class * @throws BeansException if PropertyDescriptor look fails */ public static PropertyDescriptor[] getPropertyDescriptors(Class clazz) throws BeansException { CachedIntrospectionResults cr = CachedIntrospectionResults.forClass(clazz); return cr.getBeanInfo().getPropertyDescriptors(); } /** * Retrieve the JavaBeans <code>PropertyDescriptors</code> for the given property. * @param clazz the Class to retrieve the PropertyDescriptor for * @param propertyName the name of the property * @return the corresponding PropertyDescriptor, or <code>null</code> if none * @throws BeansException if PropertyDescriptor lookup fails */ public static PropertyDescriptor getPropertyDescriptor(Class clazz, String propertyName) throws BeansException { CachedIntrospectionResults cr = CachedIntrospectionResults.forClass(clazz); return cr.getPropertyDescriptor(propertyName); } /** * Find a JavaBeans <code>PropertyDescriptor</code> for the given method, * with the method either being the read method or the write method for * that bean property. * @param method the method to find a corresponding PropertyDescriptor for * @return the corresponding PropertyDescriptor, or <code>null</code> if none * @throws BeansException if PropertyDescriptor lookup fails */ public static PropertyDescriptor findPropertyForMethod(Method method) throws BeansException { Assert.notNull(method, "Method must not be null"); PropertyDescriptor[] pds = getPropertyDescriptors(method.getDeclaringClass()); for (int i = 0; i < pds.length; i++) { PropertyDescriptor pd = pds[i]; if (method.equals(pd.getReadMethod()) || method.equals(pd.getWriteMethod())) { return pd; } } return null; } /** * Determine the bean property type for the given property from the * given classes/interfaces, if possible. * @param propertyName the name of the bean property * @param beanClasses the classes to check against * @return the property type, or <code>Object.class</code> as fallback */ public static Class findPropertyType(String propertyName, Class[] beanClasses) { if (beanClasses != null) { for (int i = 0; i < beanClasses.length; i++) { PropertyDescriptor pd = getPropertyDescriptor(beanClasses[i], propertyName); if (pd != null) { return pd.getPropertyType(); } } } return Object.class; } /** * Check if the given type represents a "simple" property: * a primitive, a String, a Class, or a corresponding array. * <p>Used to determine properties to check for a "simple" dependency-check. * @param clazz the type to check * @return whether the given type represent a "simple" property * @see org.springframework.beans.factory.support.RootBeanDefinition#DEPENDENCY_CHECK_SIMPLE * @see org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#checkDependencies */ public static boolean isSimpleProperty(Class clazz) { Assert.notNull(clazz, "Class must not be null"); return clazz.isPrimitive() || ClassUtils.isPrimitiveArray(clazz) || ClassUtils.isPrimitiveWrapper(clazz) || ClassUtils.isPrimitiveWrapperArray(clazz) || clazz.equals(String.class) || clazz.equals(String[].class) || clazz.equals(Class.class) || clazz.equals(Class[].class); } /** * Determine if the given target type is assignable from the given value * type, assuming setting by reflection. Considers primitive wrapper * classes as assignable to the corresponding primitive types. * @param targetType the target type * @param valueType the value type that should be assigned to the target type * @return if the target type is assignable from the value type * @deprecated as of Spring 2.0, in favor of <code>ClassUtils.isAssignable</code> * @see org.springframework.util.ClassUtils#isAssignable(Class, Class) */ public static boolean isAssignable(Class targetType, Class valueType) { return ClassUtils.isAssignable(targetType, valueType); } /** * Determine if the given type is assignable from the given value, * assuming setting by reflection. Considers primitive wrapper classes * as assignable to the corresponding primitive types. * @param type the target type * @param value the value that should be assigned to the type * @return if the type is assignable from the value * @deprecated as of Spring 2.0, in favor of <code>ClassUtils.isAssignableValue</code> * @see org.springframework.util.ClassUtils#isAssignableValue(Class, Object) */ public static boolean isAssignable(Class type, Object value) { return ClassUtils.isAssignableValue(type, value); } /** * Copy the property values of the given source bean into the target bean. * <p>Note: The source and target classes do not have to match or even be derived * from each other, as long as the properties match. Any bean properties that the * source bean exposes but the target bean does not will silently be ignored. * <p>This is just a convenience method. For more complex transfer needs, * consider using a full BeanWrapper. * @param source the source bean * @param target the target bean * @throws BeansException if the copying failed * @see BeanWrapper */ public static void copyProperties(Object source, Object target) throws BeansException { copyProperties(source, target, null, null); } /** * Copy the property values of the given source bean into the given target bean, * only setting properties defined in the given "editable" class (or interface). * <p>Note: The source and target classes do not have to match or even be derived * from each other, as long as the properties match. Any bean properties that the * source bean exposes but the target bean does not will silently be ignored. * <p>This is just a convenience method. For more complex transfer needs, * consider using a full BeanWrapper. * @param source the source bean * @param target the target bean * @param editable the class (or interface) to restrict property setting to * @throws BeansException if the copying failed * @see BeanWrapper */ public static void copyProperties(Object source, Object target, Class editable) throws BeansException { copyProperties(source, target, editable, null); } /** * Copy the property values of the given source bean into the given target bean, * ignoring the given "ignoreProperties". * <p>Note: The source and target classes do not have to match or even be derived * from each other, as long as the properties match. Any bean properties that the * source bean exposes but the target bean does not will silently be ignored. * <p>This is just a convenience method. For more complex transfer needs, * consider using a full BeanWrapper. * @param source the source bean * @param target the target bean * @param ignoreProperties array of property names to ignore * @throws BeansException if the copying failed * @see BeanWrapper */ public static void copyProperties(Object source, Object target, String[] ignoreProperties) throws BeansException { copyProperties(source, target, null, ignoreProperties); } /** * Copy the property values of the given source bean into the given target bean. * <p>Note: The source and target classes do not have to match or even be derived * from each other, as long as the properties match. Any bean properties that the * source bean exposes but the target bean does not will silently be ignored. * @param source the source bean * @param target the target bean * @param editable the class (or interface) to restrict property setting to * @param ignoreProperties array of property names to ignore * @throws BeansException if the copying failed * @see BeanWrapper */ 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"); 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); } } } } } }
反射方法!
相关推荐
Apache Commons BeanUtils是Java开发中的一个实用工具库,主要用于处理JavaBeans对象,简化对JavaBean属性的操作。这个库提供了一套方便的API,使得开发者可以通过简单的API调用来获取、设置JavaBean的属性,甚至...
赠送jar包:commons-beanutils-1.9.4.jar; 赠送原API文档:commons-beanutils-1.9.4-javadoc.jar; 赠送源代码:commons-beanutils-1.9.4-sources.jar; 赠送Maven依赖信息文件:commons-beanutils-1.9.4.pom; ...
赠送jar包:commons-beanutils-1.9.4.jar; 赠送原API文档:commons-beanutils-1.9.4-javadoc.jar; 赠送源代码:commons-beanutils-1.9.4-sources.jar; 赠送Maven依赖信息文件:commons-beanutils-1.9.4.pom; ...
Apache Commons BeanUtils是Java开发中的一个实用库,它提供了对JavaBeans属性的简便操作。这个库简化了在对象之间复制属性、处理集合以及调用JavaBean方法的过程。在这个"commons-beanutils-1.9.4.jar.zip"压缩包中...
Apache Commons BeanUtils是Java开发中的一个实用工具库,它提供了对JavaBeans进行操作的便捷方法。这个库的主要目的是简化对对象属性的访问,使得开发者能够更高效地处理对象的属性设置和获取,而无需手动编写大量...
Apache Commons BeanUtils是Java开发中一个非常重要的工具库,它为开发者提供了大量便捷的JavaBean操作功能。在本文中,我们将深入探讨`commons-beanutils-1.9.4`这个版本,了解其核心功能、使用场景以及如何在项目...
BeanUtils是Apache Commons项目中的一个核心库,主要提供了一组工具方法来简化Java Bean的操纵。这个1.8版本的jar包和源码是开发者在处理Java对象属性时的得力助手,尤其对于那些需要频繁进行对象属性设置和获取的...
Apache Commons BeanUtils是Java开发中的一个实用工具库,它提供了对JavaBeans属性操作的强大功能,极大地简化了在Java代码中处理对象属性的工作。这个压缩包文件"commons-beanutils所有版本(1.0-1.9.2).zip"包含了...
Apache Commons BeanUtils是Java开发中的一个实用工具库,主要用于简化对JavaBean的操作。这个`commons-beanutils-1.9.3.jar`文件是该库的一个版本,它提供了丰富的API来帮助开发者更方便地处理JavaBean对象。在这个...
《Apache Commons BeanUtils:深入解析源码》 Apache Commons BeanUtils是Java开发中常用的一个工具库,它提供了方便的Bean操作方法,简化了Java对象属性的访问和设置。本篇文章将深入探讨`commons-beanutils-1.8.0...
Apache Commons BeanUtils 1.8.3 是一个强大的Java库,专为简化Java Bean操作而设计。这个API提供了大量的实用工具方法,使得开发者能够更加便捷地处理Java对象,特别是那些符合Java Bean规范的对象。在Java编程中,...
这篇文章将对比分析Apache BeanUtils、PropertyUtils、Spring BeanUtils以及Cglib BeanCopier这四个常用的Bean复制工具的性能和特点。 首先,Apache BeanUtils是Apache Commons项目的一部分,提供了一系列便捷的...
一个BeanUtils.copyProperties的小型快速替代。 起因 由于BeanUtils(Spring或Apache Commons)的copyProperties实现是利用反射实现的,它在大量调用时具有比较严重的性能问题。 BeanMapper通过javassist类库实现在...
《Apache Commons BeanUtils详解》 Apache Commons BeanUtils是Apache软件基金会的一个开源项目,它提供了一组实用工具类,用于简化JavaBean对象的操作。这个库的核心是`org.apache.commons.beanutils`包,其中包含...
Apache Commons BeanUtils是Java开发中一个非常实用的工具库,主要功能是简化JavaBean对象的操作。这个"beanutils的jar包"是1.93版本,它包含了对bean操作的各种方法,同时也集成了log包,方便开发者进行日志记录,...
《深入解析Apache Commons BeanUtils源码》 Apache Commons BeanUtils是Java开发中广泛使用的工具库,主要用于处理JavaBean对象的属性操作。这个库的核心功能在于简化了JavaBean对象的属性设置、获取以及复制等操作...
《深入解析Apache Commons BeanUtils库》 Apache Commons BeanUtils库是Java开发中广泛使用的工具集,主要用于处理JavaBean对象的属性操作。这个库提供了一系列简便的方法,使得开发者能够轻松地进行对象属性的读取...
《Apache Commons BeanUtils 1.8.0:深入解析与应用》 Apache Commons BeanUtils库是Java开发中不可或缺的一部分,尤其对于那些频繁处理JavaBeans属性的开发者来说。它提供了便捷的方式来操作Java对象的属性,极大...
Apache Commons BeanUtils是Java开发中一个非常重要的工具库,它为开发者提供了方便的Java Bean操作接口。这个"commons-beanutils-1.8.2-src"官方源文件包,是学习和理解BeanUtils核心功能的宝贵资源。在这个版本中...
赠送jar包:commons-beanutils-1.9.3.jar; 赠送原API文档:commons-beanutils-1.9.3-javadoc.jar; 赠送源代码:commons-beanutils-1.9.3-sources.jar; 包含翻译后的API文档:commons-beanutils-1.9.3-javadoc-...