📄 methodcache.java
字号:
/* * Copyright 2001-2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package org.apache.axis.utils.cache;import java.lang.reflect.Method;import java.util.Arrays;import java.util.HashMap;import java.util.Map;import org.apache.axis.utils.ClassUtils;/** * A cache for methods. * Used to get methods by their signature and stores them in a local * cache for performance reasons. * This class is a singleton - so use getInstance to get an instance of it. * * @author Davanum Srinivas <dims@yahoo.com> * @author Sebastian Dietrich <sebastian.dietrich@anecon.com> */public class MethodCache { /** * The only instance of this class */ transient private static MethodCache instance; /** * Cache for Methods * In fact this is a map (with classes as keys) of a map (with method-names as keys) */ transient private static ThreadLocal cache; /** * The <i>private</i> constructor for this class. * Use getInstance to get an instance (the only one). */ private MethodCache() { cache = new ThreadLocal(); } /** * Gets the only instance of this class * @return the only instance of this class */ public static MethodCache getInstance() { if (instance == null) { instance = new MethodCache(); } return instance; } /** * Returns the per thread hashmap (for method caching) */ private Map getMethodCache() { Map map = (Map) cache.get(); if (map == null) { map = new HashMap(); cache.set(map); } return map; } /** * Class used as the key for the method cache table. * */ static class MethodKey { /** the name of the method in the cache */ private final String methodName; /** the list of types accepted by the method as arguments */ private final Class[] parameterTypes; /** * Creates a new <code>MethodKey</code> instance. * * @param methodName a <code>String</code> value * @param parameterTypes a <code>Class[]</code> value */ MethodKey(String methodName, Class[] parameterTypes) { this.methodName = methodName; this.parameterTypes = parameterTypes; } public boolean equals(Object other) { MethodKey that = (MethodKey) other; return this.methodName.equals(that.methodName) && Arrays.equals(this.parameterTypes, that.parameterTypes); } public int hashCode() { // allow overloaded methods to collide; we'll sort it out // in equals(). Note that String's implementation of // hashCode already caches its value, so there's no point // in doing so here. return methodName.hashCode(); } } /** used to track methods we've sought but not found in the past */ private static final Object NULL_OBJECT = new Object(); /** * Returns the specified method - if any. * * @param clazz the class to get the method from * @param methodName the name of the method * @param parameterTypes the parameters of the method * @return the found method * * @throws NoSuchMethodException if the method can't be found */ public Method getMethod(Class clazz, String methodName, Class[] parameterTypes) throws NoSuchMethodException { String className = clazz.getName(); Map cache = getMethodCache(); Method method = null; Map methods = null; // Strategy is as follows: // construct a MethodKey to represent the name/arguments // of a method's signature. // // use the name of the class to retrieve a map of that // class' methods // // if a map exists, use the MethodKey to find the // associated value object. if that object is a Method // instance, return it. if that object is anything // else, then it's a reference to our NULL_OBJECT // instance, indicating that we've previously tried // and failed to find a method meeting our requirements, // so return null // // if the map of methods for the class doesn't exist, // or if no value is associated with our key in that map, // then we perform a reflection-based search for the method. // // if we find a method in that search, we store it in the // map using the key; otherwise, we store a reference // to NULL_OBJECT using the key. // Check the cache first. MethodKey key = new MethodKey(methodName, parameterTypes); methods = (Map) cache.get(clazz); if (methods != null) { Object o = methods.get(key); if (o != null) { // cache hit if (o instanceof Method) { // good cache hit return (Method) o; } else { // bad cache hit // we hit the NULL_OBJECT, so this is a search // that previously failed; no point in doing // it again as it is a worst case search // through the entire classpath. return null; } } else { // cache miss: fall through to reflective search } } else { // cache miss: fall through to reflective search } try { method = clazz.getMethod(methodName, parameterTypes); } catch (NoSuchMethodException e1) { if (!clazz.isPrimitive() && !className.startsWith("java.") && !className.startsWith("javax.")) { try { Class helper = ClassUtils.forName(className + "_Helper"); method = helper.getMethod(methodName, parameterTypes); } catch (ClassNotFoundException e2) { } } } // first time we've seen this class: set up its method cache if (methods == null) { methods = new HashMap(); cache.put(clazz, methods); } // when no method is found, cache the NULL_OBJECT // so that we don't have to repeat worst-case searches // every time. if (null == method) { methods.put(key, NULL_OBJECT); } else { methods.put(key, method); } return method; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -