java.lang.reflect.Method (java反射机制)
2010-05-19 16:47
274 查看
公司Vac方法过滤器使用到反射机制,读取xml配置文件过滤用户访问的方法名是否合法。
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
@SuppressWarnings("unchecked")
Map<Object, Object> requestData = (Map<Object, Object>) httpRequest.getAttribute("requestData");
String methodName = (String) requestData.get(METHOD);
//获得bean的配置
String beanName = mapProtocol.get(methodName).get(BEAN);
// 去除.符号
methodName = getMethod(methodName);
//从spring context中获得bean
Object instance = getContext(filterConfig).getBean(beanName);
Class<? extends Object> clazz = instance.getClass();
Object resultContent = null;
try {
Method method = clazz
.getDeclaredMethod(methodName, getParamTypes());
Map params = removeSysParams(requestData);
resultContent = method.invoke(instance, params);
} catch (InvocationTargetException e) {
if (e.getTargetException() instanceof BusinessException) {
BusinessException serviceExp = (BusinessException) e
.getTargetException();
Assert.throwBPException(serviceExp.getMessageKey(),
serviceExp.getMessage());
}
e.printStackTrace();
Assert.throwBPException(INVOCATION_TARGET_EXP, e);
} catch (NoSuchMethodException e) {
e.printStackTrace();
Assert.throwBPException(ILLEGAL_ARGUMENT_EXP, e);
}
catch (IllegalAccessException e) {
e.printStackTrace();
Assert.throwBPException(ILLEGAL_ARGUMENT_EXP, e);
}
Enumeration enumeration = httpRequest.getAttributeNames();
while (enumeration.hasMoreElements()) {
String name = enumeration.nextElement().toString();
httpRequest.removeAttribute(name);
}
httpRequest.setAttribute(RESPONSEDATA, resultContent);
}
下面是Method类的源代码及说明:
package java.lang.reflect;
import sun.reflect.MethodAccessor;
import sun.reflect.Reflection;
/**
*
* 描述方法的类
*
* 注意使用反射的方式是首先通过
* Class.getMethod(String name, Class[] parameterTypes)获得一个Method对象
* String表示方法名,parameterTypes表示参数列表中的每个参数对应的类型,这时先获得
* Class对象中Method对象,与实际的操作对象无关,然后调用此方法,是通过Method.(Object obj, Object[] args)
* 这里obj指调用方法的对象,args表示每个参数对应的值
*
* 例子,一下两种方式的效果是一样的(当然性能不同)
* String ost = "lqtest";
* String nst = ost.substring(2,6);
*
* String ost2 = "lqtest";
* Class[] types = {int.class, int.class};
* Method med = String.class.getMethod("substring", types);
* Object[] values ={new Integer(2), new Integer(6)};
* String nst2 = (String) med.invoke(ost2, values);
*
* 使用反射一切都是变化的,类名,方法名,参数列表,都是变量,而不是写死的,他们
* 在运行时才知道具体值,而不是编译期
*
* comment by liqiang
*
* @author Kenneth Russell
* @author Nakul Saraiya
*/
public final
class Method extends AccessibleObject implements Member {
//定义此方法的类对象
private Class clazz;
private int slot;
//方法名,从1.4开始它变成intern的形式
private String name;
//返回类型
private Class returnType;
//参数列表
private Class[] parameterTypes;
//异常列表
private Class[] exceptionTypes;
//方法的描述符
private int modifiers;
//处理方法的实际对象
private volatile MethodAccessor methodAccessor;
//如果当前对象是通过拷贝得到的,则root指向拷贝前的对象
private Method root;
//调用对象的安全检查的缓存,保存上一个通过检查的调用对象,如果当前的调用对象
//不是上一个调用对象则做安全检查
private volatile Class securityCheckTargetClassCache;
//构造函数
Method(Class declaringClass,
String name,
Class[] parameterTypes,
Class returnType,
Class[] checkedExceptions,
int modifiers,
int slot)
{
this.clazz = declaringClass;
this.name = name;
this.parameterTypes = parameterTypes;
this.returnType = returnType;
this.exceptionTypes = checkedExceptions;
this.modifiers = modifiers;
this.slot = slot;
}
//通过本对象的数据生成一个新对象
Method copy() {
//通过本对象的数据生成一个新对象
Method res = new Method(clazz, name, parameterTypes, returnType,
exceptionTypes, modifiers, slot);
//新对象的root指向原对象
res.root = this;
//新对象与原对象公用一个MethodAccessor
res.methodAccessor = methodAccessor;
return res;
}
//返回声明此函数的类
public Class getDeclaringClass() {
return clazz;
}
//返回方法名
public String getName() {
return name;
}
//返回描述符
public int getModifiers() {
return modifiers;
}
//取得返回类型
public Class getReturnType() {
return returnType;
}
//返回参数列表
public Class[] getParameterTypes() {
return copy(parameterTypes);
}
//返回异常列表
public Class[] getExceptionTypes() {
return copy(exceptionTypes);
}
//判断obj是否与当前方法对象相等
public boolean equals(Object obj) {
if (obj != null && obj instanceof Method) {//如果是方法对象
//转型
Method other = (Method)obj;
//定义此方法的类和方法名相等
if ((getDeclaringClass() == other.getDeclaringClass())
&& (getName() == other.getName())) {
/* Avoid unnecessary cloning */
Class[] params1 = parameterTypes;
Class[] params2 = other.parameterTypes;
//比较参数列表
if (params1.length == params2.length) {
for (int i = 0; i < params1.length; i++) {
if (params1[i] != params2[i])
return false;
}
return true;
}
}
}
return false;
}
//返回hashCode
public int hashCode() {
return getDeclaringClass().getName().hashCode() ^ getName().hashCode();
}
//方法对象的字符串表示
public String toString() {
try {
StringBuffer sb = new StringBuffer();
int mod = getModifiers();
if (mod != 0) {
//标志符
sb.append(Modifier.toString(mod) + " ");
}
//注意它这里用的是Field方法中显示类的名字,这个方法显示数组类型跟Class.getName()不同
//添加返回类型
sb.append(Field.getTypeName(getReturnType()) + " ");
//添加类名
sb.append(Field.getTypeName(getDeclaringClass()) + ".");
//添加方法名
sb.append(getName() + "(");
//参数列表
Class[] params = parameterTypes; // avoid clone
for (int j = 0; j < params.length; j++) {
sb.append(Field.getTypeName(params[j]));
if (j < (params.length - 1))
sb.append(",");
}
sb.append(")");
//异常列表
Class[] exceptions = exceptionTypes; // avoid clone
if (exceptions.length > 0) {
sb.append(" throws ");
for (int k = 0; k < exceptions.length; k++) {
sb.append(exceptions[k].getName());
if (k < (exceptions.length - 1))
sb.append(",");
}
}
return sb.toString();
} catch (Exception e) {
return "<" + e + ">";
}
}
/**
*
* 注意使用反射的方式是首先通过
* Class.getMethod(String name, Class[] parameterTypes)获得一个Method对象
* String表示方法名,parameterTypes表示参数列表中的每个参数对应的类型,这时先获得
* Class对象中Method对象,与实际的操作对象无关,然后调用此方法,是通过Method.(Object obj, Object[] args)
* 如果调用的方法是static的则obj对象为null,如果方法没有参数,则args的长度为0或为null
* 如果返回值是原始类型则返回它的封装类,如果返回值是void则返回null
*/
public Object invoke(Object obj, Object[] args)
throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
//获得调用对象的Class对象
Class caller = Reflection.getCallerClass(1);
Class targetClass = ((obj == null || !Modifier.isProtected(modifiers))
? clazz
: obj.getClass());
//调用此操作的对象或方法调用作用的对象与缓存不同,则做安全检查
if (securityCheckCache != caller ||
targetClass != securityCheckTargetClassCache) {
Reflection.ensureMemberAccess(caller, clazz, obj, modifiers);
securityCheckCache = caller;
//通过安全检查的调用对象,缓存它供下次调用时使用
securityCheckTargetClassCache = targetClass;
}
}
}
if (methodAccessor == null) acquireMethodAccessor();
return methodAccessor.invoke(obj, args);
}
//如果此对象是由copy生成的,则对象与生成此对象的对象使用同一个MethodAccessor
private void acquireMethodAccessor() {
MethodAccessor tmp = null;
if (root != null) tmp = root.getMethodAccessor();
if (tmp != null) {
methodAccessor = tmp;
return;
}
//不是由copy得来创建MethodAccessor对象
tmp = reflectionFactory.newMethodAccessor(this);
setMethodAccessor(tmp);
}
//返回MethodAccessor对象
MethodAccessor getMethodAccessor() {
return methodAccessor;
}
//设置MethodAccessor对象
void setMethodAccessor(MethodAccessor accessor) {
methodAccessor = accessor;
if (root != null) {//如果此对象是由copy的来
//递归调用其上级
root.setMethodAccessor(accessor);
}
}
//生成一个新的Class数组并将原数组内容考到新数组中
static Class[] copy(Class[] in) {
int l = in.length;
if (l == 0)
return in;
Class[] out = new Class[l];
for (int i = 0; i < l; i++)
out[i] = in[i];
return out;
}
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
@SuppressWarnings("unchecked")
Map<Object, Object> requestData = (Map<Object, Object>) httpRequest.getAttribute("requestData");
String methodName = (String) requestData.get(METHOD);
//获得bean的配置
String beanName = mapProtocol.get(methodName).get(BEAN);
// 去除.符号
methodName = getMethod(methodName);
//从spring context中获得bean
Object instance = getContext(filterConfig).getBean(beanName);
Class<? extends Object> clazz = instance.getClass();
Object resultContent = null;
try {
Method method = clazz
.getDeclaredMethod(methodName, getParamTypes());
Map params = removeSysParams(requestData);
resultContent = method.invoke(instance, params);
} catch (InvocationTargetException e) {
if (e.getTargetException() instanceof BusinessException) {
BusinessException serviceExp = (BusinessException) e
.getTargetException();
Assert.throwBPException(serviceExp.getMessageKey(),
serviceExp.getMessage());
}
e.printStackTrace();
Assert.throwBPException(INVOCATION_TARGET_EXP, e);
} catch (NoSuchMethodException e) {
e.printStackTrace();
Assert.throwBPException(ILLEGAL_ARGUMENT_EXP, e);
}
catch (IllegalAccessException e) {
e.printStackTrace();
Assert.throwBPException(ILLEGAL_ARGUMENT_EXP, e);
}
Enumeration enumeration = httpRequest.getAttributeNames();
while (enumeration.hasMoreElements()) {
String name = enumeration.nextElement().toString();
httpRequest.removeAttribute(name);
}
httpRequest.setAttribute(RESPONSEDATA, resultContent);
}
下面是Method类的源代码及说明:
package java.lang.reflect;
import sun.reflect.MethodAccessor;
import sun.reflect.Reflection;
/**
*
* 描述方法的类
*
* 注意使用反射的方式是首先通过
* Class.getMethod(String name, Class[] parameterTypes)获得一个Method对象
* String表示方法名,parameterTypes表示参数列表中的每个参数对应的类型,这时先获得
* Class对象中Method对象,与实际的操作对象无关,然后调用此方法,是通过Method.(Object obj, Object[] args)
* 这里obj指调用方法的对象,args表示每个参数对应的值
*
* 例子,一下两种方式的效果是一样的(当然性能不同)
* String ost = "lqtest";
* String nst = ost.substring(2,6);
*
* String ost2 = "lqtest";
* Class[] types = {int.class, int.class};
* Method med = String.class.getMethod("substring", types);
* Object[] values ={new Integer(2), new Integer(6)};
* String nst2 = (String) med.invoke(ost2, values);
*
* 使用反射一切都是变化的,类名,方法名,参数列表,都是变量,而不是写死的,他们
* 在运行时才知道具体值,而不是编译期
*
* comment by liqiang
*
* @author Kenneth Russell
* @author Nakul Saraiya
*/
public final
class Method extends AccessibleObject implements Member {
//定义此方法的类对象
private Class clazz;
private int slot;
//方法名,从1.4开始它变成intern的形式
private String name;
//返回类型
private Class returnType;
//参数列表
private Class[] parameterTypes;
//异常列表
private Class[] exceptionTypes;
//方法的描述符
private int modifiers;
//处理方法的实际对象
private volatile MethodAccessor methodAccessor;
//如果当前对象是通过拷贝得到的,则root指向拷贝前的对象
private Method root;
//调用对象的安全检查的缓存,保存上一个通过检查的调用对象,如果当前的调用对象
//不是上一个调用对象则做安全检查
private volatile Class securityCheckTargetClassCache;
//构造函数
Method(Class declaringClass,
String name,
Class[] parameterTypes,
Class returnType,
Class[] checkedExceptions,
int modifiers,
int slot)
{
this.clazz = declaringClass;
this.name = name;
this.parameterTypes = parameterTypes;
this.returnType = returnType;
this.exceptionTypes = checkedExceptions;
this.modifiers = modifiers;
this.slot = slot;
}
//通过本对象的数据生成一个新对象
Method copy() {
//通过本对象的数据生成一个新对象
Method res = new Method(clazz, name, parameterTypes, returnType,
exceptionTypes, modifiers, slot);
//新对象的root指向原对象
res.root = this;
//新对象与原对象公用一个MethodAccessor
res.methodAccessor = methodAccessor;
return res;
}
//返回声明此函数的类
public Class getDeclaringClass() {
return clazz;
}
//返回方法名
public String getName() {
return name;
}
//返回描述符
public int getModifiers() {
return modifiers;
}
//取得返回类型
public Class getReturnType() {
return returnType;
}
//返回参数列表
public Class[] getParameterTypes() {
return copy(parameterTypes);
}
//返回异常列表
public Class[] getExceptionTypes() {
return copy(exceptionTypes);
}
//判断obj是否与当前方法对象相等
public boolean equals(Object obj) {
if (obj != null && obj instanceof Method) {//如果是方法对象
//转型
Method other = (Method)obj;
//定义此方法的类和方法名相等
if ((getDeclaringClass() == other.getDeclaringClass())
&& (getName() == other.getName())) {
/* Avoid unnecessary cloning */
Class[] params1 = parameterTypes;
Class[] params2 = other.parameterTypes;
//比较参数列表
if (params1.length == params2.length) {
for (int i = 0; i < params1.length; i++) {
if (params1[i] != params2[i])
return false;
}
return true;
}
}
}
return false;
}
//返回hashCode
public int hashCode() {
return getDeclaringClass().getName().hashCode() ^ getName().hashCode();
}
//方法对象的字符串表示
public String toString() {
try {
StringBuffer sb = new StringBuffer();
int mod = getModifiers();
if (mod != 0) {
//标志符
sb.append(Modifier.toString(mod) + " ");
}
//注意它这里用的是Field方法中显示类的名字,这个方法显示数组类型跟Class.getName()不同
//添加返回类型
sb.append(Field.getTypeName(getReturnType()) + " ");
//添加类名
sb.append(Field.getTypeName(getDeclaringClass()) + ".");
//添加方法名
sb.append(getName() + "(");
//参数列表
Class[] params = parameterTypes; // avoid clone
for (int j = 0; j < params.length; j++) {
sb.append(Field.getTypeName(params[j]));
if (j < (params.length - 1))
sb.append(",");
}
sb.append(")");
//异常列表
Class[] exceptions = exceptionTypes; // avoid clone
if (exceptions.length > 0) {
sb.append(" throws ");
for (int k = 0; k < exceptions.length; k++) {
sb.append(exceptions[k].getName());
if (k < (exceptions.length - 1))
sb.append(",");
}
}
return sb.toString();
} catch (Exception e) {
return "<" + e + ">";
}
}
/**
*
* 注意使用反射的方式是首先通过
* Class.getMethod(String name, Class[] parameterTypes)获得一个Method对象
* String表示方法名,parameterTypes表示参数列表中的每个参数对应的类型,这时先获得
* Class对象中Method对象,与实际的操作对象无关,然后调用此方法,是通过Method.(Object obj, Object[] args)
* 如果调用的方法是static的则obj对象为null,如果方法没有参数,则args的长度为0或为null
* 如果返回值是原始类型则返回它的封装类,如果返回值是void则返回null
*/
public Object invoke(Object obj, Object[] args)
throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
//获得调用对象的Class对象
Class caller = Reflection.getCallerClass(1);
Class targetClass = ((obj == null || !Modifier.isProtected(modifiers))
? clazz
: obj.getClass());
//调用此操作的对象或方法调用作用的对象与缓存不同,则做安全检查
if (securityCheckCache != caller ||
targetClass != securityCheckTargetClassCache) {
Reflection.ensureMemberAccess(caller, clazz, obj, modifiers);
securityCheckCache = caller;
//通过安全检查的调用对象,缓存它供下次调用时使用
securityCheckTargetClassCache = targetClass;
}
}
}
if (methodAccessor == null) acquireMethodAccessor();
return methodAccessor.invoke(obj, args);
}
//如果此对象是由copy生成的,则对象与生成此对象的对象使用同一个MethodAccessor
private void acquireMethodAccessor() {
MethodAccessor tmp = null;
if (root != null) tmp = root.getMethodAccessor();
if (tmp != null) {
methodAccessor = tmp;
return;
}
//不是由copy得来创建MethodAccessor对象
tmp = reflectionFactory.newMethodAccessor(this);
setMethodAccessor(tmp);
}
//返回MethodAccessor对象
MethodAccessor getMethodAccessor() {
return methodAccessor;
}
//设置MethodAccessor对象
void setMethodAccessor(MethodAccessor accessor) {
methodAccessor = accessor;
if (root != null) {//如果此对象是由copy的来
//递归调用其上级
root.setMethodAccessor(accessor);
}
}
//生成一个新的Class数组并将原数组内容考到新数组中
static Class[] copy(Class[] in) {
int l = in.length;
if (l == 0)
return in;
Class[] out = new Class[l];
for (int i = 0; i < l; i++)
out[i] = in[i];
return out;
}
}
相关文章推荐
- java.lang.reflect.Method (java反射机制)
- Java反射机制学习(二)java.lang.reflect.Array
- Java.lang.reflect 下的Class,Method,Field的使用实例
- JAVA反射系列之Method,java.lang.reflect.Method的使用
- Java反射之java.lang.reflect.Method
- (转)Java.lang.reflect.Method invoke方法 实例
- JAVA反射系列之Method,java.lang.reflect.Method的使用
- JAVA反射系列之Method,java.lang.reflect.Method的使用
- 关于java.lang.reflect.Field 和 java.lang.reflect.Method 的问题
- java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0
- Java.lang.reflect.Method invoke方法 实例
- JAVA反射系列之Method,java.lang.reflect.Method的使用。
- Disabling contextual LOB creation as createClob() method error : java.lang.reflect.InvocationTargetE
- JAVA反射系列之Method,java.lang.reflect.Method的使用
- Spring启动时报异常:No String constructor found on type [java.lang.reflect.Method]
- Java.lang.reflect.Method invoke
- method threw error : java.lang.reflect.InvocationTargetException
- Disabling contextual LOB creation as createClob() method threw error : java.lang.reflect.Invocation
- Java.lang.reflect.Method invoke方法 实例
- Disabling contextual LOB creation as createClob() method threw error : java.lang.reflect.InvocationT