您的位置:首页 > 编程语言 > Java开发

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;

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: