通过名称从Java Bean获取属性
/** from * n o w j a v a . c o m - 时代Java **/ /* * Copyright (c) 2012 EDC * * This file is part of Stepping Stone. * * Stepping Stone is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Stepping Stone is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Stepping Stone. If not, see <http://www.gnu.org/licenses/gpl.txt>. */ import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.Array; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Main{ public static void main(String[] argv) throws Exception{ Object bean = "nowjava.com"; String propName = "nowjava.com"; System.out.println(getProperty(bean,propName)); } private static final Pattern DOTTED_PATH_SPLITTER = Pattern .compile("\\."); /** 来自 时代Java公众号 - N o w J a v a . c o m**/ private static final Pattern SEQUENCE_PATTERN = Pattern .compile("^(\\w+)\\[(\\d+)\\]$"); public static Object getProperty(Object bean, String propName) { Object ret = bean; String[] parts = DOTTED_PATH_SPLITTER.split(propName); try { for (String part : parts) { Matcher matcher = null; if ((matcher = partContainsIndex(part)) != null) { part = matcher.group(1); int idx = Integer.parseInt(matcher.group(2)); Method m = determineGetterMethod(ret, part); ret = m.invoke(ret); if (ret instanceof List<?>) { ret = ((List<?>) ret).get(idx); } else { ret = Array.get(ret, idx); } } else { Method m = determineGetterMethod(ret, part); ret = m.invoke(ret); } } } catch (IllegalArgumentException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (InvocationTargetException e) { throw new RuntimeException(e); } catch (IntrospectionException e) { throw new RuntimeException(e); } return ret; } private static Matcher partContainsIndex(String part) { Matcher m = null; if (part.endsWith("]") && (m = SEQUENCE_PATTERN.matcher(part)).find()) { return m; } return null; } public static Method determineGetterMethod(Object bean, String beanPropName) throws IntrospectionException { return determineAccessorMethod(bean, beanPropName, null, AccessorType.GETTER); } public static Method determineGetterMethod(Object bean, String beanPropName, Class<?> paramClass) throws IntrospectionException { return determineAccessorMethod(bean, beanPropName, paramClass, AccessorType.GETTER); } private static Method determineAccessorMethod(Object bean, String beanPropName, Class<?> parameterClass, AccessorType accessorType) throws IntrospectionException { Method ret = null; BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass()); PropertyDescriptor[] propertyDescriptors = beanInfo .getPropertyDescriptors(); PD_ITER: for (PropertyDescriptor pd : propertyDescriptors) { if (beanPropName.equals(pd.getName())) { // If we do not specify a param type, match by name-only if (parameterClass == null) { return accessorType == AccessorType.SETTER ? pd .getWriteMethod() : pd.getReadMethod(); } Method m = null; Class<?> methodParamType = null; switch (accessorType) { case SETTER: m = pd.getWriteMethod(); Class<?>[] paramTypes = m.getParameterTypes(); if (paramTypes.length == 1) { methodParamType = paramTypes[0]; } break; case GETTER: m = pd.getReadMethod(); if (m != null) { methodParamType = m.getReturnType(); } break; } if (m == null || methodParamType == null) { continue PD_ITER; } // e.g., Number isAssignableFrom Integer if (methodParamType.equals(parameterClass) || methodParamType .isAssignableFrom((parameterClass))) { ret = m; break PD_ITER; } else if (methodParamType.isPrimitive()) { if (Number.class.isAssignableFrom(parameterClass)) { if ((Integer.class == parameterClass && Integer.TYPE == methodParamType) || (Short.class == parameterClass && Short.TYPE == methodParamType)