zoukankan      html  css  js  c++  java
  • java.lang.reflect.Method (java反射机制)

    公司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类的源代码及说明:

    1. package java.lang.reflect;   
    2.   
    3. import sun.reflect.MethodAccessor;   
    4. import sun.reflect.Reflection;   
    5.   
    6. /**  
    7.  *   
    8.  * 描述方法的类  
    9.  *   
    10.  * 注意使用反射的方式是首先通过  
    11.  * Class.getMethod(String name, Class[] parameterTypes)获得一个Method对象  
    12.  * String表示方法名,parameterTypes表示参数列表中的每个参数对应的类型,这时先获得  
    13.  * Class对象中Method对象,与实际的操作对象无关,然后调用此方法,是通过Method.(Object obj, Object[] args)  
    14.  * 这里obj指调用方法的对象,args表示每个参数对应的值  
    15.  *   
    16.  * 例子,一下两种方式的效果是一样的(当然性能不同)  
    17.  * String ost = "lqtest";  
    18.  * String nst = ost.substring(2,6);  
    19.  *   
    20.  * String ost2 = "lqtest";  
    21.  * Class[] types = {int.class, int.class};  
    22.  * Method med = String.class.getMethod("substring", types);  
    23.  * Object[] values ={new Integer(2), new Integer(6)};  
    24.  * String nst2 = (String) med.invoke(ost2, values);  
    25.  *   
    26.  * 使用反射一切都是变化的,类名,方法名,参数列表,都是变量,而不是写死的,他们  
    27.  * 在运行时才知道具体值,而不是编译期  
    28.  *   
    29.  * comment by liqiang  
    30.  *  
    31.  * @author Kenneth Russell  
    32.  * @author Nakul Saraiya  
    33.  */  
    34. public final  
    35. class Method extends AccessibleObject implements Member {   
    36.  //定义此方法的类对象   
    37.     private Class  clazz;   
    38.     private int   slot;   
    39.     //方法名,从1.4开始它变成intern的形式   
    40.     private String  name;   
    41.     //返回类型   
    42.     private Class  returnType;   
    43.     //参数列表   
    44.     private Class[]  parameterTypes;   
    45.     //异常列表   
    46.     private Class[]  exceptionTypes;   
    47.     //方法的描述符   
    48.     private int   modifiers;   
    49.     //处理方法的实际对象   
    50.     private volatile MethodAccessor methodAccessor;   
    51.     //如果当前对象是通过拷贝得到的,则root指向拷贝前的对象   
    52.     private Method              root;   
    53.   
    54.     //调用对象的安全检查的缓存,保存上一个通过检查的调用对象,如果当前的调用对象   
    55.     //不是上一个调用对象则做安全检查   
    56.     private volatile Class      securityCheckTargetClassCache;   
    57.   
    58.     //构造函数   
    59.     Method(Class declaringClass,   
    60.            String name,   
    61.            Class[] parameterTypes,   
    62.            Class returnType,   
    63.            Class[] checkedExceptions,   
    64.            int modifiers,   
    65.            int slot)   
    66.     {   
    67.         this.clazz = declaringClass;   
    68.         this.name = name;   
    69.         this.parameterTypes = parameterTypes;   
    70.         this.returnType = returnType;   
    71.         this.exceptionTypes = checkedExceptions;   
    72.         this.modifiers = modifiers;   
    73.         this.slot = slot;   
    74.     }   
    75.   
    76.     //通过本对象的数据生成一个新对象   
    77.     Method copy() {   
    78.      //通过本对象的数据生成一个新对象   
    79.         Method res = new Method(clazz, name, parameterTypes, returnType,   
    80.                                 exceptionTypes, modifiers, slot);   
    81.         //新对象的root指向原对象   
    82.         res.root = this;   
    83.         //新对象与原对象公用一个MethodAccessor   
    84.         res.methodAccessor = methodAccessor;   
    85.         return res;   
    86.     }   
    87.   
    88.     //返回声明此函数的类   
    89.     public Class getDeclaringClass() {   
    90.  return clazz;   
    91.     }   
    92.   
    93.     //返回方法名   
    94.     public String getName() {   
    95.  return name;   
    96.     }   
    97.   
    98.     //返回描述符   
    99.     public int getModifiers() {   
    100.  return modifiers;   
    101.     }   
    102.   
    103.     //取得返回类型   
    104.     public Class getReturnType() {   
    105.  return returnType;   
    106.     }   
    107.   
    108.     //返回参数列表   
    109.     public Class[] getParameterTypes() {   
    110.  return copy(parameterTypes);   
    111.     }   
    112.   
    113.     //返回异常列表   
    114.     public Class[] getExceptionTypes() {   
    115.  return copy(exceptionTypes);   
    116.     }   
    117.   
    118.     //判断obj是否与当前方法对象相等   
    119.     public boolean equals(Object obj) {   
    120.  if (obj != null && obj instanceof Method) {//如果是方法对象   
    121.   //转型   
    122.      Method other = (Method)obj;   
    123.         
    124.      //定义此方法的类和方法名相等   
    125.      if ((getDeclaringClass() == other.getDeclaringClass())   
    126.   && (getName() == other.getName())) {   
    127.          
    128.   /* Avoid unnecessary cloning */  
    129.   Class[] params1 = parameterTypes;   
    130.   Class[] params2 = other.parameterTypes;   
    131.      
    132.   //比较参数列表   
    133.   if (params1.length == params2.length) {   
    134.       for (int i = 0; i < params1.length; i++) {   
    135.    if (params1[i] != params2[i])   
    136.        return false;   
    137.       }   
    138.       return true;   
    139.   }   
    140.      
    141.      }   
    142.  }   
    143.  return false;   
    144.     }   
    145.   
    146.     //返回hashCode   
    147.     public int hashCode() {   
    148.  return getDeclaringClass().getName().hashCode() ^ getName().hashCode();   
    149.     }   
    150.   
    151.     //方法对象的字符串表示   
    152.     public String toString() {   
    153.  try {   
    154.      StringBuffer sb = new StringBuffer();   
    155.      int mod = getModifiers();   
    156.      if (mod != 0) {   
    157.      //标志符   
    158.   sb.append(Modifier.toString(mod) + " ");   
    159.      }   
    160.      //注意它这里用的是Field方法中显示类的名字,这个方法显示数组类型跟Class.getName()不同   
    161.      //添加返回类型   
    162.      sb.append(Field.getTypeName(getReturnType()) + " ");   
    163.      //添加类名   
    164.      sb.append(Field.getTypeName(getDeclaringClass()) + ".");   
    165.      //添加方法名   
    166.      sb.append(getName() + "(");       
    167.         
    168.      //参数列表   
    169.      Class[] params = parameterTypes; // avoid clone   
    170.      for (int j = 0; j < params.length; j++) {   
    171.   sb.append(Field.getTypeName(params[j]));   
    172.   if (j < (params.length - 1))   
    173.       sb.append(",");   
    174.      }   
    175.      sb.append(")");   
    176.         
    177.      //异常列表   
    178.      Class[] exceptions = exceptionTypes; // avoid clone   
    179.      if (exceptions.length > 0) {   
    180.   sb.append(" throws ");   
    181.   for (int k = 0; k < exceptions.length; k++) {   
    182.       sb.append(exceptions[k].getName());   
    183.       if (k < (exceptions.length - 1))   
    184.    sb.append(",");   
    185.   }   
    186.      }   
    187.      return sb.toString();   
    188.  } catch (Exception e) {   
    189.      return "<" + e + ">";   
    190.  }   
    191.     }   
    192.   
    193.     /**  
    194.      *   
    195.      * 注意使用反射的方式是首先通过  
    196.      * Class.getMethod(String name, Class[] parameterTypes)获得一个Method对象  
    197.      * String表示方法名,parameterTypes表示参数列表中的每个参数对应的类型,这时先获得  
    198.      * Class对象中Method对象,与实际的操作对象无关,然后调用此方法,是通过Method.(Object obj, Object[] args)  
    199.      * 如果调用的方法是static的则obj对象为null,如果方法没有参数,则args的长度为0或为null  
    200.      * 如果返回值是原始类型则返回它的封装类,如果返回值是void则返回null  
    201.      */  
    202.     public Object invoke(Object obj, Object[] args)   
    203.  throws IllegalAccessException, IllegalArgumentException,   
    204.            InvocationTargetException   
    205.     {   
    206.         if (!override) {   
    207.             if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {   
    208.              //获得调用对象的Class对象   
    209.                 Class caller = Reflection.getCallerClass(1);   
    210.                    
    211.                 Class targetClass = ((obj == null || !Modifier.isProtected(modifiers))   
    212.                                      ? clazz   
    213.                                      : obj.getClass());   
    214.                 //调用此操作的对象或方法调用作用的对象与缓存不同,则做安全检查   
    215.                 if (securityCheckCache != caller ||   
    216.                     targetClass != securityCheckTargetClassCache) {   
    217.                     Reflection.ensureMemberAccess(caller, clazz, obj, modifiers);   
    218.                     securityCheckCache = caller;   
    219.                     //通过安全检查的调用对象,缓存它供下次调用时使用   
    220.                     securityCheckTargetClassCache = targetClass;   
    221.                 }   
    222.             }   
    223.         }   
    224.            
    225.         if (methodAccessor == null) acquireMethodAccessor();   
    226.         return methodAccessor.invoke(obj, args);   
    227.     }   
    228.   
    229.     //如果此对象是由copy生成的,则对象与生成此对象的对象使用同一个MethodAccessor   
    230.     private void acquireMethodAccessor() {   
    231.         MethodAccessor tmp = null;   
    232.            
    233.         if (root != null) tmp = root.getMethodAccessor();   
    234.         if (tmp != null) {   
    235.             methodAccessor = tmp;   
    236.             return;   
    237.         }   
    238.            
    239.         //不是由copy得来创建MethodAccessor对象   
    240.         tmp = reflectionFactory.newMethodAccessor(this);   
    241.         setMethodAccessor(tmp);   
    242.     }   
    243.   
    244.     //返回MethodAccessor对象   
    245.     MethodAccessor getMethodAccessor() {   
    246.         return methodAccessor;   
    247.     }   
    248.   
    249.     //设置MethodAccessor对象   
    250.     void setMethodAccessor(MethodAccessor accessor) {   
    251.         methodAccessor = accessor;   
    252.         if (root != null) {//如果此对象是由copy的来   
    253.          //递归调用其上级   
    254.             root.setMethodAccessor(accessor);   
    255.         }   
    256.     }   
    257.   
    258.     //生成一个新的Class数组并将原数组内容考到新数组中   
    259.     static Class[] copy(Class[] in) {   
    260.  int l = in.length;   
    261.     
    262.  if (l == 0)   
    263.      return in;   
    264.     
    265.  Class[] out = new Class[l];   
    266.  for (int i = 0; i < l; i++)   
    267.      out[i] = in[i];   
    268.     
    269.  return out;   
    270.     }   
    271. }  

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    ubuntu下安装flash
    PHPMailer邮件发送
    PHP制作简单分页(从数据库读取记录)
    windows下安装PHP环境
    捕获浏览器关闭,刷新事件
    ubuntu下安装wps
    用PHP制作一个简单的验证码
    一个PHP程序员应该掌握的10项技能!
    爬虫框架之scrapy
    Android杂谈禁止TimePicker控件通过keyboard输入
  • 原文地址:https://www.cnblogs.com/cuker919/p/4878621.html
Copyright © 2011-2022 走看看