- 浏览: 7340397 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (1546)
- 企业中间件 (236)
- 企业应用面临的问题 (236)
- 小布Oracle学习笔记汇总 (36)
- Spring 开发应用 (54)
- IBatis开发应用 (16)
- Oracle基础学习 (23)
- struts2.0 (41)
- JVM&ClassLoader&GC (16)
- JQuery的开发应用 (17)
- WebService的开发应用 (21)
- Java&Socket (44)
- 开源组件的应用 (254)
- 常用Javascript的开发应用 (28)
- J2EE开发技术指南 (163)
- EJB3开发应用 (11)
- GIS&Mobile&MAP (36)
- SWT-GEF-RCP (52)
- 算法&数据结构 (6)
- Apache开源组件研究 (62)
- Hibernate 学习应用 (57)
- java并发编程 (59)
- MySQL&Mongodb&MS/SQL (15)
- Oracle数据库实验室 (55)
- 搜索引擎的开发应用 (34)
- 软件工程师笔试经典 (14)
- 其他杂项 (10)
- AndroidPn& MQTT&C2DM&推技术 (29)
- ActiveMQ学习和研究 (38)
- Google技术应用开发和API分析 (11)
- flex的学习总结 (59)
- 项目中一点总结 (20)
- java疑惑 java面向对象编程 (28)
- Android 开发学习 (133)
- linux和UNIX的总结 (37)
- Titanium学习总结 (20)
- JQueryMobile学习总结 (34)
- Phonegap学习总结 (32)
- HTML5学习总结 (41)
- JeeCMS研究和理解分析 (9)
最新评论
-
lgh1992314:
[u][i][b][flash=200,200][url][i ...
看看mybatis 源代码 -
尼古拉斯.fwp:
图片根本就不出来好吧。。。。。。
Android文件图片上传的详细讲解(一)HTTP multipart/form-data 上传报文格式实现手机端上传 -
ln94223:
第一个应该用排它网关吧 怎么是并行网关, 并行网关是所有exe ...
工作流Activiti的学习总结(八)Activiti自动执行的应用 -
ZY199266:
获取不到任何消息信息,请问这是什么原因呢?
ActiveMQ 通过JMX监控Connection,Queue,Topic的信息 -
xiaoyao霄:
DestinationSourceMonitor 报错 应该导 ...
ActiveMQ 通过JMX监控Connection,Queue,Topic的信息
Apache的BeanUtils中的常用的反射类:BeanUtils,PropertyUtils,MethodUtils的学习。
学习时查阅可以使用:
public class MethodUtils {
// --------------------------------------------------------- Private Methods
/**
* Only log warning about accessibility work around once.
* <p>
* Note that this is broken when this class is deployed via a shared
* classloader in a container, as the warning message will be emitted
* only once, not once per webapp. However making the warning appear
* once per webapp means having a map keyed by context classloader
* which introduces nasty memory-leak problems. As this warning is
* really optional we can ignore this problem; only one of the webapps
* will get the warning in its logs but that should be good enough.
*/
private static boolean loggedAccessibleWarning = false;
/**
* Indicates whether methods should be cached for improved performance.
* <p>
* Note that when this class is deployed via a shared classloader in
* a container, this will affect all webapps. However making this
* configurable per webapp would mean having a map keyed by context classloader
* which may introduce memory-leak problems.
*/
private static boolean CACHE_METHODS = true;
/** An empty class array */
private static final Class[] EMPTY_CLASS_PARAMETERS = new Class[0];
/** An empty object array */
private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
/**
* Stores a cache of MethodDescriptor -> Method in a WeakHashMap.
* <p>
* The keys into this map only ever exist as temporary variables within
* methods of this class, and are never exposed to users of this class.
* This means that the WeakHashMap is used only as a mechanism for
* limiting the size of the cache, ie a way to tell the garbage collector
* that the contents of the cache can be completely garbage-collected
* whenever it needs the memory. Whether this is a good approach to
* this problem is doubtful; something like the commons-collections
* LRUMap may be more appropriate (though of course selecting an
* appropriate size is an issue).
* <p>
* This static variable is safe even when this code is deployed via a
* shared classloader because it is keyed via a MethodDescriptor object
* which has a Class as one of its members and that member is used in
* the MethodDescriptor.equals method. So two components that load the same
* class via different classloaders will generate non-equal MethodDescriptor
* objects and hence end up with different entries in the map.
*/
private static final WeakFastHashMap cache = new WeakFastHashMap();
// --------------------------------------------------------- Public Methods
static {
cache.setFast(true);
}
/**
* Set whether methods should be cached for greater performance or not,
* default is <code>true</code>.
*
* @param cacheMethods <code>true</code> if methods should be
* cached for greater performance, otherwise <code>false</code>
*/
public static synchronized void setCacheMethods(boolean cacheMethods) {
CACHE_METHODS = cacheMethods;
if (!CACHE_METHODS) {
clearCache();
}
}
/**
* Clear the method cache.
* @return the number of cached methods cleared
*/
public static synchronized int clearCache() {
int size = cache.size();
cache.clear();
return size;
}
/**
* <p>Invoke a named method whose parameter type matches the object type.</p>
*
* <p>The behaviour of this method is less deterministic
* than <code>invokeExactMethod()</code>.
* It loops through all methods with names that match
* and then executes the first it finds with compatable parameters.</p>
*
* <p>This method supports calls to methods taking primitive parameters
* via passing in wrapping classes. So, for example, a <code>Boolean</code> class
* would match a <code>boolean</code> primitive.</p>
*
* <p> This is a convenient wrapper for
* {@link #invokeMethod(Object object,String methodName,Object [] args)}.
* </p>
*
* @param object invoke method on this object
* @param methodName get method with this name
* @param arg use this argument
* @return The value returned by the invoked method
*
* @throws NoSuchMethodException if there is no such accessible method
* @throws InvocationTargetException wraps an exception thrown by the
* method invoked
* @throws IllegalAccessException if the requested method is not accessible
* via reflection
*/
public static Object invokeMethod(
Object object,
String methodName,
Object arg)
throws
NoSuchMethodException,
IllegalAccessException,
InvocationTargetException {
Object[] args = {arg};
return invokeMethod(object, methodName, args);
}
/**
* <p>Invoke a named method whose parameter type matches the object type.</p>
*
* <p>The behaviour of this method is less deterministic
* than {@link #invokeExactMethod(Object object,String methodName,Object [] args)}.
* It loops through all methods with names that match
* and then executes the first it finds with compatable parameters.</p>
*
* <p>This method supports calls to methods taking primitive parameters
* via passing in wrapping classes. So, for example, a <code>Boolean</code> class
* would match a <code>boolean</code> primitive.</p>
*
* <p> This is a convenient wrapper for
* {@link #invokeMethod(Object object,String methodName,Object [] args,Class[] parameterTypes)}.
* </p>
*
* @param object invoke method on this object
* @param methodName get method with this name
* @param args use these arguments - treat null as empty array
* @return The value returned by the invoked method
*
* @throws NoSuchMethodException if there is no such accessible method
* @throws InvocationTargetException wraps an exception thrown by the
* method invoked
* @throws IllegalAccessException if the requested method is not accessible
* via reflection
*/
public static Object invokeMethod(
Object object,
String methodName,
Object[] args)
throws
NoSuchMethodException,
IllegalAccessException,
InvocationTargetException {
if (args == null) {
args = EMPTY_OBJECT_ARRAY;
}
int arguments = args.length;
Class[] parameterTypes = new Class[arguments];
for (int i = 0; i < arguments; i++) {
parameterTypes[i] = args[i].getClass();
}
return invokeMethod(object, methodName, args, parameterTypes);
}
/**
* <p>Invoke a named method whose parameter type matches the object type.</p>
*
* <p>The behaviour of this method is less deterministic
* than {@link
* #invokeExactMethod(Object object,String methodName,Object [] args,Class[] parameterTypes)}.
* It loops through all methods with names that match
* and then executes the first it finds with compatable parameters.</p>
*
* <p>This method supports calls to methods taking primitive parameters
* via passing in wrapping classes. So, for example, a <code>Boolean</code> class
* would match a <code>boolean</code> primitive.</p>
*
*
* @param object invoke method on this object
* @param methodName get method with this name
* @param args use these arguments - treat null as empty array
* @param parameterTypes match these parameters - treat null as empty array
* @return The value returned by the invoked method
*
* @throws NoSuchMethodException if there is no such accessible method
* @throws InvocationTargetException wraps an exception thrown by the
* method invoked
* @throws IllegalAccessException if the requested method is not accessible
* via reflection
*/
public static Object invokeMethod(
Object object,
String methodName,
Object[] args,
Class[] parameterTypes)
throws
NoSuchMethodException,
IllegalAccessException,
InvocationTargetException {
if (parameterTypes == null) {
parameterTypes = EMPTY_CLASS_PARAMETERS;
}
if (args == null) {
args = EMPTY_OBJECT_ARRAY;
}
Method method = getMatchingAccessibleMethod(
object.getClass(),
methodName,
parameterTypes);
if (method == null) {
throw new NoSuchMethodException("No such accessible method: " +
methodName + "() on object: " + object.getClass().getName());
}
return method.invoke(object, args);
}
/**
* <p>Invoke a method whose parameter type matches exactly the object
* type.</p>
*
* <p> This is a convenient wrapper for
* {@link #invokeExactMethod(Object object,String methodName,Object [] args)}.
* </p>
*
* @param object invoke method on this object
* @param methodName get method with this name
* @param arg use this argument
* @return The value returned by the invoked method
*
* @throws NoSuchMethodException if there is no such accessible method
* @throws InvocationTargetException wraps an exception thrown by the
* method invoked
* @throws IllegalAccessException if the requested method is not accessible
* via reflection
*/
public static Object invokeExactMethod(
Object object,
String methodName,
Object arg)
throws
NoSuchMethodException,
IllegalAccessException,
InvocationTargetException {
Object[] args = {arg};
return invokeExactMethod(object, methodName, args);
}
/**
* <p>Invoke a method whose parameter types match exactly the object
* types.</p>
*
* <p> This uses reflection to invoke the method obtained from a call to
* <code>getAccessibleMethod()</code>.</p>
*
* @param object invoke method on this object
* @param methodName get method with this name
* @param args use these arguments - treat null as empty array
* @return The value returned by the invoked method
*
* @throws NoSuchMethodException if there is no such accessible method
* @throws InvocationTargetException wraps an exception thrown by the
* method invoked
* @throws IllegalAccessException if the requested method is not accessible
* via reflection
*/
public static Object invokeExactMethod(
Object object,
String methodName,
Object[] args)
throws
NoSuchMethodException,
IllegalAccessException,
InvocationTargetException {
if (args == null) {
args = EMPTY_OBJECT_ARRAY;
}
int arguments = args.length;
Class[] parameterTypes = new Class[arguments];
for (int i = 0; i < arguments; i++) {
parameterTypes[i] = args[i].getClass();
}
return invokeExactMethod(object, methodName, args, parameterTypes);
}
/**
* <p>Invoke a method whose parameter types match exactly the parameter
* types given.</p>
*
* <p>This uses reflection to invoke the method obtained from a call to
* <code>getAccessibleMethod()</code>.</p>
*
* @param object invoke method on this object
* @param methodName get method with this name
* @param args use these arguments - treat null as empty array
* @param parameterTypes match these parameters - treat null as empty array
* @return The value returned by the invoked method
*
* @throws NoSuchMethodException if there is no such accessible method
* @throws InvocationTargetException wraps an exception thrown by the
* method invoked
* @throws IllegalAccessException if the requested method is not accessible
* via reflection
*/
public static Object invokeExactMethod(
Object object,
String methodName,
Object[] args,
Class[] parameterTypes)
throws
NoSuchMethodException,
IllegalAccessException,
InvocationTargetException {
if (args == null) {
args = EMPTY_OBJECT_ARRAY;
}
if (parameterTypes == null) {
parameterTypes = EMPTY_CLASS_PARAMETERS;
}
Method method = getAccessibleMethod(
object.getClass(),
methodName,
parameterTypes);
if (method == null) {
throw new NoSuchMethodException("No such accessible method: " +
methodName + "() on object: " + object.getClass().getName());
}
return method.invoke(object, args);
}
/**
* <p>Invoke a static method whose parameter types match exactly the parameter
* types given.</p>
*
* <p>This uses reflection to invoke the method obtained from a call to
* {@link #getAccessibleMethod(Class, String, Class[])}.</p>
*
* @param objectClass invoke static method on this class
* @param methodName get method with this name
* @param args use these arguments - treat null as empty array
* @param parameterTypes match these parameters - treat null as empty array
* @return The value returned by the invoked method
*
* @throws NoSuchMethodException if there is no such accessible method
* @throws InvocationTargetException wraps an exception thrown by the
* method invoked
* @throws IllegalAccessException if the requested method is not accessible
* via reflection
*/
public static Object invokeExactStaticMethod(
Class objectClass,
String methodName,
Object[] args,
Class[] parameterTypes)
throws
NoSuchMethodException,
IllegalAccessException,
InvocationTargetException {
if (args == null) {
args = EMPTY_OBJECT_ARRAY;
}
if (parameterTypes == null) {
parameterTypes = EMPTY_CLASS_PARAMETERS;
}
Method method = getAccessibleMethod(
objectClass,
methodName,
parameterTypes);
if (method == null) {
throw new NoSuchMethodException("No such accessible method: " +
methodName + "() on class: " + objectClass.getName());
}
return method.invoke(null, args);
}
/**
* <p>Invoke a named static method whose parameter type matches the object type.</p>
*
* <p>The behaviour of this method is less deterministic
* than {@link #invokeExactMethod(Object, String, Object[], Class[])}.
* It loops through all methods with names that match
* and then executes the first it finds with compatable parameters.</p>
*
* <p>This method supports calls to methods taking primitive parameters
* via passing in wrapping classes. So, for example, a <code>Boolean</code> class
* would match a <code>boolean</code> primitive.</p>
*
* <p> This is a convenient wrapper for
* {@link #invokeStaticMethod(Class objectClass,String methodName,Object [] args)}.
* </p>
*
* @param objectClass invoke static method on this class
* @param methodName get method with this name
* @param arg use this argument
* @return The value returned by the invoked method
*
* @throws NoSuchMethodException if there is no such accessible method
* @throws InvocationTargetException wraps an exception thrown by the
* method invoked
* @throws IllegalAccessException if the requested method is not accessible
* via reflection
*/
public static Object invokeStaticMethod(
Class objectClass,
String methodName,
Object arg)
throws
NoSuchMethodException,
IllegalAccessException,
InvocationTargetException {
Object[] args = {arg};
return invokeStaticMethod (objectClass, methodName, args);
}
/**
* <p>Invoke a named static method whose parameter type matches the object type.</p>
*
* <p>The behaviour of this method is less deterministic
* than {@link #invokeExactMethod(Object object,String methodName,Object [] args)}.
* It loops through all methods with names that match
* and then executes the first it finds with compatable parameters.</p>
*
* <p>This method supports calls to methods taking primitive parameters
* via passing in wrapping classes. So, for example, a <code>Boolean</code> class
* would match a <code>boolean</code> primitive.</p>
*
* <p> This is a convenient wrapper for
* {@link #invokeStaticMethod(Class objectClass,String methodName,Object [] args,Class[] parameterTypes)}.
* </p>
*
* @param objectClass invoke static method on this class
* @param methodName get method with this name
* @param args use these arguments - treat null as empty array
* @return The value returned by the invoked method
*
* @throws NoSuchMethodException if there is no such accessible method
* @throws InvocationTargetException wraps an exception thrown by the
* method invoked
* @throws IllegalAccessException if the requested method is not accessible
* via reflection
*/
public static Object invokeStaticMethod(
Class objectClass,
String methodName,
Object[] args)
throws
NoSuchMethodException,
IllegalAccessException,
InvocationTargetException {
if (args == null) {
args = EMPTY_OBJECT_ARRAY;
}
int arguments = args.length;
Class[] parameterTypes = new Class[arguments];
for (int i = 0; i < arguments; i++) {
parameterTypes[i] = args[i].getClass();
}
return invokeStaticMethod (objectClass, methodName, args, parameterTypes);
}
/**
* <p>Invoke a named static method whose parameter type matches the object type.</p>
*
* <p>The behaviour of this method is less deterministic
* than {@link
* #invokeExactStaticMethod(Class objectClass,String methodName,Object [] args,Class[] parameterTypes)}.
* It loops through all methods with names that match
* and then executes the first it finds with compatable parameters.</p>
*
* <p>This method supports calls to methods taking primitive parameters
* via passing in wrapping classes. So, for example, a <code>Boolean</code> class
* would match a <code>boolean</code> primitive.</p>
*
*
* @param objectClass invoke static method on this class
* @param methodName get method with this name
* @param args use these arguments - treat null as empty array
* @param parameterTypes match these parameters - treat null as empty array
* @return The value returned by the invoked method
*
* @throws NoSuchMethodException if there is no such accessible method
* @throws InvocationTargetException wraps an exception thrown by the
* method invoked
* @throws IllegalAccessException if the requested method is not accessible
* via reflection
*/
public static Object invokeStaticMethod(
Class objectClass,
String methodName,
Object[] args,
Class[] parameterTypes)
throws
NoSuchMethodException,
IllegalAccessException,
InvocationTargetException {
if (parameterTypes == null) {
parameterTypes = EMPTY_CLASS_PARAMETERS;
}
if (args == null) {
args = EMPTY_OBJECT_ARRAY;
}
Method method = getMatchingAccessibleMethod(
objectClass,
methodName,
parameterTypes);
if (method == null) {
throw new NoSuchMethodException("No such accessible method: " +
methodName + "() on class: " + objectClass.getName());
}
return method.invoke(null, args);
}
/**
* <p>Invoke a static method whose parameter type matches exactly the object
* type.</p>
*
* <p> This is a convenient wrapper for
* {@link #invokeExactStaticMethod(Class objectClass,String methodName,Object [] args)}.
* </p>
*
* @param objectClass invoke static method on this class
* @param methodName get method with this name
* @param arg use this argument
* @return The value returned by the invoked method
*
* @throws NoSuchMethodException if there is no such accessible method
* @throws InvocationTargetException wraps an exception thrown by the
* method invoked
* @throws IllegalAccessException if the requested method is not accessible
* via reflection
*/
public static Object invokeExactStaticMethod(
Class objectClass,
String methodName,
Object arg)
throws
NoSuchMethodException,
IllegalAccessException,
InvocationTargetException {
Object[] args = {arg};
return invokeExactStaticMethod (objectClass, methodName, args);
}
/**
* <p>Invoke a static method whose parameter types match exactly the object
* types.</p>
*
* <p> This uses reflection to invoke the method obtained from a call to
* {@link #getAccessibleMethod(Class, String, Class[])}.</p>
*
* @param objectClass invoke static method on this class
* @param methodName get method with this name
* @param args use these arguments - treat null as empty array
* @return The value returned by the invoked method
*
* @throws NoSuchMethodException if there is no such accessible method
* @throws InvocationTargetException wraps an exception thrown by the
* method invoked
* @throws IllegalAccessException if the requested method is not accessible
* via reflection
*/
public static Object invokeExactStaticMethod(
Class objectClass,
String methodName,
Object[] args)
throws
NoSuchMethodException,
IllegalAccessException,
InvocationTargetException {
if (args == null) {
args = EMPTY_OBJECT_ARRAY;
}
int arguments = args.length;
Class[] parameterTypes = new Class[arguments];
for (int i = 0; i < arguments; i++) {
parameterTypes[i] = args[i].getClass();
}
return invokeExactStaticMethod(objectClass, methodName, args, parameterTypes);
}
/**
* <p>Return an accessible method (that is, one that can be invoked via
* reflection) with given name and a single parameter. If no such method
* can be found, return <code>null</code>.
* Basically, a convenience wrapper that constructs a <code>Class</code>
* array for you.</p>
*
* @param clazz get method from this class
* @param methodName get method with this name
* @param parameterType taking this type of parameter
* @return The accessible method
*/
public static Method getAccessibleMethod(
Class clazz,
String methodName,
Class parameterType) {
Class[] parameterTypes = {parameterType};
return getAccessibleMethod(clazz, methodName, parameterTypes);
}
/**
* <p>Return an accessible method (that is, one that can be invoked via
* reflection) with given name and parameters. If no such method
* can be found, return <code>null</code>.
* This is just a convenient wrapper for
* {@link #getAccessibleMethod(Method method)}.</p>
*
* @param clazz get method from this class
* @param methodName get method with this name
* @param parameterTypes with these parameters types
* @return The accessible method
*/
public static Method getAccessibleMethod(
Class clazz,
String methodName,
Class[] parameterTypes) {
try {
MethodDescriptor md = new MethodDescriptor(clazz, methodName, parameterTypes, true);
// Check the cache first
Method method = getCachedMethod(md);
if (method != null) {
return method;
}
method = getAccessibleMethod
(clazz, clazz.getMethod(methodName, parameterTypes));
cacheMethod(md, method);
return method;
} catch (NoSuchMethodException e) {
return (null);
}
}
/**
* <p>Return an accessible method (that is, one that can be invoked via
* reflection) that implements the specified Method. If no such method
* can be found, return <code>null</code>.</p>
*
* @param method The method that we wish to call
* @return The accessible method
*/
public static Method getAccessibleMethod(Method method) {
// Make sure we have a method to check
if (method == null) {
return (null);
}
return getAccessibleMethod(method.getDeclaringClass(), method);
}
/**
* <p>Return an accessible method (that is, one that can be invoked via
* reflection) that implements the specified Method. If no such method
* can be found, return <code>null</code>.</p>
*
* @param clazz The class of the object
* @param method The method that we wish to call
* @return The accessible method
*/
public static Method getAccessibleMethod(Class clazz, Method method) {
// Make sure we have a method to check
if (method == null) {
return (null);
}
// If the requested method is not public we cannot call it
if (!Modifier.isPublic(method.getModifiers())) {
return (null);
}
boolean sameClass = true;
if (clazz == null) {
clazz = method.getDeclaringClass();
} else {
sameClass = clazz.equals(method.getDeclaringClass());
if (!method.getDeclaringClass().isAssignableFrom(clazz)) {
throw new IllegalArgumentException(clazz.getName() +
" is not assignable from " + method.getDeclaringClass().getName());
}
}
// If the class is public, we are done
if (Modifier.isPublic(clazz.getModifiers())) {
if (!sameClass && !Modifier.isPublic(method.getDeclaringClass().getModifiers())) {
setMethodAccessible(method); // Default access superclass workaround
}
return (method);
}
String methodName = method.getName();
Class[] parameterTypes = method.getParameterTypes();
// Check the implemented interfaces and subinterfaces
method =
getAccessibleMethodFromInterfaceNest(clazz,
methodName,
parameterTypes);
// Check the superclass chain
if (method == null) {
method = getAccessibleMethodFromSuperclass(clazz,
methodName,
parameterTypes);
}
return (method);
}
// -------------------------------------------------------- Private Methods
/**
* <p>Return an accessible method (that is, one that can be invoked via
* reflection) by scanning through the superclasses. If no such method
* can be found, return <code>null</code>.</p>
*
* @param clazz Class to be checked
* @param methodName Method name of the method we wish to call
* @param parameterTypes The parameter type signatures
*/
private static Method getAccessibleMethodFromSuperclass
(Class clazz, String methodName, Class[] parameterTypes) {
Class parentClazz = clazz.getSuperclass();
while (parentClazz != null) {
if (Modifier.isPublic(parentClazz.getModifiers())) {
try {
return parentClazz.getMethod(methodName, parameterTypes);
} catch (NoSuchMethodException e) {
return null;
}
}
parentClazz = parentClazz.getSuperclass();
}
return null;
}
/**
* <p>Return an accessible method (that is, one that can be invoked via
* reflection) that implements the specified method, by scanning through
* all implemented interfaces and subinterfaces. If no such method
* can be found, return <code>null</code>.</p>
*
* <p> There isn't any good reason why this method must be private.
* It is because there doesn't seem any reason why other classes should
* call this rather than the higher level methods.</p>
*
* @param clazz Parent class for the interfaces to be checked
* @param methodName Method name of the method we wish to call
* @param parameterTypes The parameter type signatures
*/
private static Method getAccessibleMethodFromInterfaceNest
(Class clazz, String methodName, Class[] parameterTypes) {
Method method = null;
// Search up the superclass chain
for (; clazz != null; clazz = clazz.getSuperclass()) {
// Check the implemented interfaces of the parent class
Class[] interfaces = clazz.getInterfaces();
for (int i = 0; i < interfaces.length; i++) {
// Is this interface public?
if (!Modifier.isPublic(interfaces[i].getModifiers())) {
continue;
}
// Does the method exist on this interface?
try {
method = interfaces[i].getDeclaredMethod(methodName,
parameterTypes);
} catch (NoSuchMethodException e) {
/* Swallow, if no method is found after the loop then this
* method returns null.
*/
}
if (method != null) {
return method;
}
// Recursively check our parent interfaces
method =
getAccessibleMethodFromInterfaceNest(interfaces[i],
methodName,
parameterTypes);
if (method != null) {
return method;
}
}
}
// If we found a method return it
if (method != null) {
return (method);
}
// We did not find anything
return (null);
}
/**
* <p>Find an accessible method that matches the given name and has compatible parameters.
* Compatible parameters mean that every method parameter is assignable from
* the given parameters.
* In other words, it finds a method with the given name
* that will take the parameters given.<p>
*
* <p>This method is slightly undeterminstic since it loops
* through methods names and return the first matching method.</p>
*
* <p>This method is used by
* {@link
* #invokeMethod(Object object,String methodName,Object [] args,Class[] parameterTypes)}.
*
* <p>This method can match primitive parameter by passing in wrapper classes.
* For example, a <code>Boolean</code> will match a primitive <code>boolean</code>
* parameter.
*
* @param clazz find method in this class
* @param methodName find method with this name
* @param parameterTypes find method with compatible parameters
* @return The accessible method
*/
public static Method getMatchingAccessibleMethod(
Class clazz,
String methodName,
Class[] parameterTypes) {
// trace logging
Log log = LogFactory.getLog(MethodUtils.class);
if (log.isTraceEnabled()) {
log.trace("Matching name=" + methodName + " on " + clazz);
}
MethodDescriptor md = new MethodDescriptor(clazz, methodName, parameterTypes, false);
// see if we can find the method directly
// most of the time this works and it's much faster
try {
// Check the cache first
Method method = getCachedMethod(md);
if (method != null) {
return method;
}
method = clazz.getMethod(methodName, parameterTypes);
if (log.isTraceEnabled()) {
log.trace("Found straight match: " + method);
log.trace("isPublic:" + Modifier.isPublic(method.getModifiers()));
}
setMethodAccessible(method); // Default access superclass workaround
cacheMethod(md, method);
return method;
} catch (NoSuchMethodException e) { /* SWALLOW */ }
// search through all methods
int paramSize = parameterTypes.length;
Method bestMatch = null;
Method[] methods = clazz.getMethods();
float bestMatchCost = Float.MAX_VALUE;
float myCost = Float.MAX_VALUE;
for (int i = 0, size = methods.length; i < size ; i++) {
if (methods[i].getName().equals(methodName)) {
// log some trace information
if (log.isTraceEnabled()) {
log.trace("Found matching name:");
log.trace(methods[i]);
}
// compare parameters
Class[] methodsParams = methods[i].getParameterTypes();
int methodParamSize = methodsParams.length;
if (methodParamSize == paramSize) {
boolean match = true;
for (int n = 0 ; n < methodParamSize; n++) {
if (log.isTraceEnabled()) {
log.trace("Param=" + parameterTypes[n].getName());
log.trace("Method=" + methodsParams[n].getName());
}
if (!isAssignmentCompatible(methodsParams[n], parameterTypes[n])) {
if (log.isTraceEnabled()) {
log.trace(methodsParams[n] + " is not assignable from "
+ parameterTypes[n]);
}
match = false;
break;
}
}
if (match) {
// get accessible version of method
Method method = getAccessibleMethod(clazz, methods[i]);
if (method != null) {
if (log.isTraceEnabled()) {
log.trace(method + " accessible version of "
+ methods[i]);
}
setMethodAccessible(method); // Default access superclass workaround
myCost = getTotalTransformationCost(parameterTypes,method.getParameterTypes());
if ( myCost < bestMatchCost ) {
bestMatch = method;
bestMatchCost = myCost;
}
}
log.trace("Couldn't find accessible method.");
}
}
}
}
if ( bestMatch != null ){
cacheMethod(md, bestMatch);
} else {
// didn't find a match
log.trace("No match found.");
}
return bestMatch;
}
/**
* Try to make the method accessible
* @param method The source arguments
*/
private static void setMethodAccessible(Method method) {
try {
//
// XXX Default access superclass workaround
//
// When a public class has a default access superclass
// with public methods, these methods are accessible.
// Calling them from compiled code works fine.
//
// Unfortunately, using reflection to invoke these methods
// seems to (wrongly) to prevent access even when the method
// modifer is public.
//
// The following workaround solves the problem but will only
// work from sufficiently privilages code.
//
// Better workarounds would be greatfully accepted.
//
method.setAccessible(true);
} catch (SecurityException se) {
// log but continue just in case the method.invoke works anyway
Log log = LogFactory.getLog(MethodUtils.class);
if (!loggedAccessibleWarning) {
boolean vulnerableJVM = false;
try {
String specVersion = System.getProperty("java.specification.version");
if (specVersion.charAt(0) == '1' &&
(specVersion.charAt(2) == '0' ||
specVersion.charAt(2) == '1' ||
specVersion.charAt(2) == '2' ||
specVersion.charAt(2) == '3')) {
vulnerableJVM = true;
}
} catch (SecurityException e) {
// don't know - so display warning
vulnerableJVM = true;
}
if (vulnerableJVM) {
log.warn(
"Current Security Manager restricts use of workarounds for reflection bugs "
+ " in pre-1.4 JVMs.");
}
loggedAccessibleWarning = true;
}
log.debug("Cannot setAccessible on method. Therefore cannot use jvm access bug workaround.", se);
}
}
/**
* Returns the sum of the object transformation cost for each class in the source
* argument list.
* @param srcArgs The source arguments
* @param destArgs The destination arguments
* @return The total transformation cost
*/
private static float getTotalTransformationCost(Class[] srcArgs, Class[] destArgs) {
float totalCost = 0.0f;
for (int i = 0; i < srcArgs.length; i++) {
Class srcClass, destClass;
srcClass = srcArgs[i];
destClass = destArgs[i];
totalCost += getObjectTransformationCost(srcClass, destClass);
}
return totalCost;
}
/**
* Gets the number of steps required needed to turn the source class into the
* destination class. This represents the number of steps in the object hierarchy
* graph.
* @param srcClass The source class
* @param destClass The destination class
* @return The cost of transforming an object
*/
private static float getObjectTransformationCost(Class srcClass, Class destClass) {
float cost = 0.0f;
while (destClass != null && !destClass.equals(srcClass)) {
if (destClass.isInterface() && isAssignmentCompatible(destClass,srcClass)) {
// slight penalty for interface match.
// we still want an exact match to override an interface match, but
// an interface match should override anything where we have to get a
// superclass.
cost += 0.25f;
break;
}
cost++;
destClass = destClass.getSuperclass();
}
/*
* If the destination class is null, we've travelled all the way up to
* an Object match. We'll penalize this by adding 1.5 to the cost.
*/
if (destClass == null) {
cost += 1.5f;
}
return cost;
}
/**
* <p>Determine whether a type can be used as a parameter in a method invocation.
* This method handles primitive conversions correctly.</p>
*
* <p>In order words, it will match a <code>Boolean</code> to a <code>boolean</code>,
* a <code>Long</code> to a <code>long</code>,
* a <code>Float</code> to a <code>float</code>,
* a <code>Integer</code> to a <code>int</code>,
* and a <code>Double</code> to a <code>double</code>.
* Now logic widening matches are allowed.
* For example, a <code>Long</code> will not match a <code>int</code>.
*
* @param parameterType the type of parameter accepted by the method
* @param parameterization the type of parameter being tested
*
* @return true if the assignement is compatible.
*/
public static final boolean isAssignmentCompatible(Class parameterType, Class parameterization) {
// try plain assignment
if (parameterType.isAssignableFrom(parameterization)) {
return true;
}
if (parameterType.isPrimitive()) {
// this method does *not* do widening - you must specify exactly
// is this the right behaviour?
Class parameterWrapperClazz = getPrimitiveWrapper(parameterType);
if (parameterWrapperClazz != null) {
return parameterWrapperClazz.equals(parameterization);
}
}
return false;
}
/**
* Gets the wrapper object class for the given primitive type class.
* For example, passing <code>boolean.class</code> returns <code>Boolean.class</code>
* @param primitiveType the primitive type class for which a match is to be found
* @return the wrapper type associated with the given primitive
* or null if no match is found
*/
public static Class getPrimitiveWrapper(Class primitiveType) {
// does anyone know a better strategy than comparing names?
if (boolean.class.equals(primitiveType)) {
return Boolean.class;
} else if (float.class.equals(primitiveType)) {
return Float.class;
} else if (long.class.equals(primitiveType)) {
return Long.class;
} else if (int.class.equals(primitiveType)) {
return Integer.class;
} else if (short.class.equals(primitiveType)) {
return Short.class;
} else if (byte.class.equals(primitiveType)) {
return Byte.class;
} else if (double.class.equals(primitiveType)) {
return Double.class;
} else if (char.class.equals(primitiveType)) {
return Character.class;
} else {
return null;
}
}
/**
* Gets the class for the primitive type corresponding to the primitive wrapper class given.
* For example, an instance of <code>Boolean.class</code> returns a <code>boolean.class</code>.
* @param wrapperType the
* @return the primitive type class corresponding to the given wrapper class,
* null if no match is found
*/
public static Class getPrimitiveType(Class wrapperType) {
// does anyone know a better strategy than comparing names?
if (Boolean.class.equals(wrapperType)) {
return boolean.class;
} else if (Float.class.equals(wrapperType)) {
return float.class;
} else if (Long.class.equals(wrapperType)) {
return long.class;
} else if (Integer.class.equals(wrapperType)) {
return int.class;
} else if (Short.class.equals(wrapperType)) {
return short.class;
} else if (Byte.class.equals(wrapperType)) {
return byte.class;
} else if (Double.class.equals(wrapperType)) {
return double.class;
} else if (Character.class.equals(wrapperType)) {
return char.class;
} else {
Log log = LogFactory.getLog(MethodUtils.class);
if (log.isDebugEnabled()) {
log.debug("Not a known primitive wrapper class: " + wrapperType);
}
return null;
}
}
/**
* Find a non primitive representation for given primitive class.
*
* @param clazz the class to find a representation for, not null
* @return the original class if it not a primitive. Otherwise the wrapper class. Not null
*/
public static Class toNonPrimitiveClass(Class clazz) {
if (clazz.isPrimitive()) {
Class primitiveClazz = MethodUtils.getPrimitiveWrapper(clazz);
// the above method returns
if (primitiveClazz != null) {
return primitiveClazz;
} else {
return clazz;
}
} else {
return clazz;
}
}
/**
* Return the method from the cache, if present.
*
* @param md The method descriptor
* @return The cached method
*/
private static Method getCachedMethod(MethodDescriptor md) {
if (CACHE_METHODS) {
Reference methodRef = (Reference)cache.get(md);
if (methodRef != null) {
return (Method)methodRef.get();
}
}
return null;
}
/**
* Add a method to the cache.
*
* @param md The method descriptor
* @param method The method to cache
*/
private static void cacheMethod(MethodDescriptor md, Method method) {
if (CACHE_METHODS) {
if (method != null) {
cache.put(md, new WeakReference(method));
}
}
}
/**
* Represents the key to looking up a Method by reflection.
*/
private static class MethodDescriptor {
private Class cls;
private String methodName;
private Class[] paramTypes;
private boolean exact;
private int hashCode;
/**
* The sole constructor.
*
* @param cls the class to reflect, must not be null
* @param methodName the method name to obtain
* @param paramTypes the array of classes representing the paramater types
* @param exact whether the match has to be exact.
*/
public MethodDescriptor(Class cls, String methodName, Class[] paramTypes, boolean exact) {
if (cls == null) {
throw new IllegalArgumentException("Class cannot be null");
}
if (methodName == null) {
throw new IllegalArgumentException("Method Name cannot be null");
}
if (paramTypes == null) {
paramTypes = EMPTY_CLASS_PARAMETERS;
}
this.cls = cls;
this.methodName = methodName;
this.paramTypes = paramTypes;
this.exact= exact;
this.hashCode = methodName.length();
}
/**
* Checks for equality.
* @param obj object to be tested for equality
* @return true, if the object describes the same Method.
*/
public boolean equals(Object obj) {
if (!(obj instanceof MethodDescriptor)) {
return false;
}
MethodDescriptor md = (MethodDescriptor)obj;
return (
exact == md.exact &&
methodName.equals(md.methodName) &&
cls.equals(md.cls) &&
java.util.Arrays.equals(paramTypes, md.paramTypes)
);
}
/**
* Returns the string length of method name. I.e. if the
* hashcodes are different, the objects are different. If the
* hashcodes are the same, need to use the equals method to
* determine equality.
* @return the string length of method name.
*/
public int hashCode() {
return hashCode;
}
}
}
发表评论
-
【转】在项目中使用多个数据源-多sessionFactory方案
2013-05-10 16:30 3131适用范围:适合SSH架构访问多个数据库, ... -
【转】使用spring的动态路由实现数据库负载均衡
2013-03-17 22:57 3309使用spring的动态路由实现数据库负载均衡 系统中 ... -
【转】spring 数据库读写分离
2013-03-17 22:56 2805什么是数据库的读写分离 数据库的读写分离简单的说是把对数据 ... -
[转]Spring+iBatis+JOTM实现JTA事务
2013-03-17 22:51 3060Spring+iBatis+JOTM实现JTA事务 ... -
Spring 和Axis2整合相关那些事
2012-12-29 12:58 10421Axis2优劣: 现在用axis2开发一个webse ... -
【转】JAVA并发容器代码随读
2012-12-06 15:29 2954转载自 http://rdc.taobao.c ... -
Spring3.04和Junit4
2011-11-27 18:15 4396在Spring3.x以上必须采用 ... -
Spring加载属性文件的扩展
2011-08-22 12:21 3026在项目中一个属性文件配置信息,提供给数据连接信息 ... -
Brap和Spring整合(简单权限验证)
2011-07-26 10:31 1390在使用Spring的发 ... -
Quartz的任务的临时启动和暂停和恢复
2011-07-16 10:18 40228在项目中需要手动启停某些服务,那么需要有一个控 ... -
Quartz中定时调度EJB3.0服务
2011-07-13 22:25 2938在quartz2.0中只支持EJb2.0的服务 ... -
Quartz中定时调度EJB2.0服务
2011-07-13 22:12 2181在Quartz2.0中提供支持EJB2.0 ... -
Quartz的简单使用
2011-07-13 22:05 9956最近工作需要学习quartz,那么必须首先了解三个概念:调度器 ... -
Brap 远程访问调用 和Spring整合(二)
2010-12-08 14:52 2006Brap和 Spring 整合使用如 ... -
闲着没事Hessian开发WebService的总结(二)
2010-12-07 20:30 4034在Spring和Hessian整合中,以前 ... -
Spring JMX的学习总结(三) 基于注释的JMX的使用
2010-12-03 17:26 3362具体实现JMX的注释的类: package c ... -
Spring JMX的总结学习(二) 注解实现MBean
2010-12-03 17:24 6284本文采用Spring JMX ... -
Spring JMX的总结学习(一)基于标准接口的JMX
2010-12-03 17:21 3781在Spring中采用JMX标准形式的,开发相关的Spr ... -
Spring JMS的开发应用--自定义消息转换器的使用(四)
2010-12-03 01:37 2512在Spring JMS、中可以通过实现Me ... -
Spring JBOSSMQ JMS的开发应用(三)
2010-11-30 20:11 2345如果用过JMS的话,会发现它类似写JD ...
相关推荐
Spring框架中的BeanUtils继承自Apache BeanUtils,并进行了扩展,增加了对SpEL表达式的支持。Spring BeanUtils在安全性和灵活性上有所提升,例如可以自定义转换策略。然而,由于依赖于Spring框架,它的使用场景可能...
总结来说,Apache Commons BeanUtils是Java开发中的得力助手,它极大地提高了处理JavaBean对象的效率,减少了代码的冗余,同时也为处理复杂的数据操作提供了便利。通过使用这个库,开发者可以更专注于业务逻辑,而非...
Apache Commons BeanUtils Apache Commons BeanUtils为反射和自省提供了一个易于使用但灵活的包装器。文献资料可以在上找到更多信息。 可以浏览 。 与Apache Commons BeanUtils的用法有关的问题应张贴到。在哪里可以...
Apache BeanUtils是Apache Commons项目中的一个模块,它提供了一组工具类来简化JavaBean操作。在Java开发中,BeanUtils库极大地提高了开发效率,尤其是在处理对象属性的设置、获取以及复制等方面。以下是对Apache ...
commons-beanutils, Apache Commons Beanutils的镜像 Apache Commons BeanUtils Apache Commons BeanUtils提供了一个 easy-to-use,但它围绕反射。文档更多信息可以在公共BeanUtils主页上找到。 可以浏览 JavaDoc插
Apache Commons BeanUtils是Java开发中的一个实用工具库,它提供了对JavaBeans进行操作的便捷方法。这个库的主要目的是简化对对象属性的访问,使得开发者能够更高效地处理对象的属性设置和获取,而无需手动编写大量...
- 在实际开发中,了解并掌握BeanUtils的内部工作原理,可以帮助我们更高效地使用这个库,避免不必要的性能损耗,同时也可以从中学习到如何优雅地使用反射和异常处理。 总结来说,Apache Commons BeanUtils是Java...
Apache Commons BeanUtils是Java开发中的一个实用工具库,主要用于处理JavaBeans对象,简化对JavaBean属性的操作。这个库提供了一套方便的API,使得开发者可以通过简单的API调用来获取、设置JavaBean的属性,甚至...
Apache Commons BeanUtils 是一个强大的工具库,主要用于简化JavaBean的操作,极大地提高了开发效率。这个库提供了许多方便的方法,使得开发者可以便捷地对JavaBean的属性进行读取和设置,而无需手动编写大量的...
Apache Commons BeanUtils是Java开发中的一个实用库,它提供了对JavaBeans属性的简便操作。这个库简化了在对象之间复制属性、处理集合以及调用JavaBean方法的过程。在这个"commons-beanutils-1.9.4.jar.zip"压缩包中...
Apache Commons BeanUtils是Java开发中的一个非常重要的工具包,它属于Apache软件基金会的Commons项目。这个工具包提供了大量方便的API,极大地简化了JavaBean对象之间的属性操作,尤其是在处理复杂的对象模型和数据...
而Apache Commons BeanUtils库则为这些操作提供了便利,它通过反射机制来动态地访问和修改JavaBean的属性,使得代码更加简洁和易维护。 1. **属性访问与设置** BeanUtils库的核心功能就是属性的访问和设置。通过`...
Apache Commons BeanUtils是Java开发中一个非常重要的工具库,它为开发者提供了方便的Java Bean操作接口。这个"commons-beanutils-1.8.2-src"官方源文件包,是学习和理解BeanUtils核心功能的宝贵资源。在这个版本中...
Apache BeanUtils库是Java开发中的一个关键工具,它在标题"beanutils-1.8.3开发包"中被提及,表明这是一个针对该版本的BeanUtils的完整开发资源集合。这个包提供了对JavaBeans属性操作的强大支持,简化了对象属性的...
在Java编程中,Apache Commons BeanUtils库是一个不可或缺的工具包,尤其在处理JavaBean对象时,它提供了极大的便利性。本篇文章将深入探讨Apache Commons BeanUtils的核心功能、使用场景以及如何有效地利用这个库来...
在使用BeanUtils之前,需要将Apache Commons BeanUtils的jar包和Apache Commons Logging的jar包添加到项目依赖中。这两个库可以从Apache官方网站下载,链接在描述中给出。 在示例程序中,`TestJavaBean`类展示了...
下面我们将深入探讨Apache Commons BeanUtils 1.8.3的核心功能、使用场景及其在实际开发中的重要性。 1. **JavaBeans规范** JavaBeans是一种符合特定规范的Java类,通常用于封装数据并提供属性、构造器和事件处理...
通过对BeanUtils源码的学习,开发者不仅可以掌握这个工具库的使用,还能深化对Java反射、属性操作、异常处理等核心概念的理解,对于提升Java开发能力大有裨益。同时,这种源码级别的学习也是提升编程技能的重要途径...
在项目中使用Apache Commons BeanUtils,首先需要将其jar包("commons-beanutils-1.8.0.jar")添加到项目的类路径中。然后,可以直接通过import导入相应的类和方法,如`org.apache.commons.beanutils.BeanUtils`,...