mirror of https://github.com/apache/openjpa.git
OPENJPA-1113 - Cache Reflection artifacts for performance improvement.
git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@780881 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
35d97a14d3
commit
e32f6f1337
|
@ -21,20 +21,24 @@ package org.apache.openjpa.enhance;
|
|||
import java.lang.reflect.AccessibleObject;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.security.AccessController;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.openjpa.lib.util.J2DoPrivHelper;
|
||||
import org.apache.openjpa.lib.util.Localizer;
|
||||
import org.apache.openjpa.lib.util.Reflectable;
|
||||
import org.apache.openjpa.util.GeneralException;
|
||||
import org.apache.openjpa.util.UserException;
|
||||
import org.apache.openjpa.util.GeneralException;
|
||||
import org.apache.openjpa.util.UserException;
|
||||
|
||||
/**
|
||||
* Reflection utilities used to support and augment enhancement. Used both
|
||||
|
@ -47,14 +51,89 @@ public class Reflection {
|
|||
private static final Localizer _loc = Localizer.forPackage
|
||||
(Reflection.class);
|
||||
|
||||
// Weak HashMap caches of getter/setter/beanProperty methods
|
||||
private static Map<Class<?>, Map<String, Method>> getterMethodCache =
|
||||
new WeakHashMap<Class<?>, Map<String, Method>>();
|
||||
private static Map<Class<?>, Map<String, Method>> setterMethodCache =
|
||||
new WeakHashMap<Class<?>, Map<String, Method>>();
|
||||
private static Map<Class<?>, Set<String>> beanPropertiesNameCache =
|
||||
new WeakHashMap<Class<?>, Set<String>>();
|
||||
|
||||
private static Method getGetterMethod(Class<?> cls, String prop) {
|
||||
Method rtnMethod = null;
|
||||
Map<String, Method> clsMap = getterMethodCache.get(cls);
|
||||
if (clsMap != null) {
|
||||
rtnMethod = clsMap.get(prop);
|
||||
}
|
||||
return rtnMethod;
|
||||
}
|
||||
|
||||
private static void setGetterMethod(Class<?> cls, String prop,
|
||||
Method method) {
|
||||
Map<String, Method> clsMap = getterMethodCache.get(cls);
|
||||
if (clsMap == null) {
|
||||
clsMap = new HashMap<String, Method>();
|
||||
getterMethodCache.put(cls, clsMap);
|
||||
}
|
||||
clsMap.put(prop, method);
|
||||
}
|
||||
|
||||
private static Method getSetterMethod(Class<?> cls, String prop) {
|
||||
Method rtnMethod = null;
|
||||
Map<String, Method> clsMap = setterMethodCache.get(cls);
|
||||
if (clsMap != null) {
|
||||
rtnMethod = clsMap.get(prop);
|
||||
}
|
||||
return rtnMethod;
|
||||
}
|
||||
|
||||
private static void setSetterMethod(Class<?> cls, String prop,
|
||||
Method method) {
|
||||
Map<String, Method> clsMap = setterMethodCache.get(cls);
|
||||
if (clsMap == null) {
|
||||
clsMap = new HashMap<String, Method>();
|
||||
setterMethodCache.put(cls, clsMap);
|
||||
}
|
||||
clsMap.put(prop, method);
|
||||
}
|
||||
|
||||
public static void flushCaches() {
|
||||
getterMethodCache.clear();
|
||||
setterMethodCache.clear();
|
||||
beanPropertiesNameCache.clear();
|
||||
}
|
||||
|
||||
public static void flushCaches(Collection<ClassLoader> loaders) {
|
||||
if (loaders.size() > 0) {
|
||||
flushCache(loaders, getterMethodCache);
|
||||
flushCache(loaders, setterMethodCache);
|
||||
flushCache(loaders, beanPropertiesNameCache);
|
||||
}
|
||||
}
|
||||
|
||||
private static void flushCache(Collection<ClassLoader> loaders,
|
||||
Map<Class<?>, ?> cache) {
|
||||
for (Iterator<Class<?>> itr = cache.keySet().iterator();
|
||||
itr.hasNext();) {
|
||||
Class<?> cls = itr.next();
|
||||
ClassLoader sLoader = cls.getClassLoader();
|
||||
if (loaders.contains(sLoader)) {
|
||||
itr.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the getter method matching the given property name, optionally
|
||||
* throwing an exception if none.
|
||||
*/
|
||||
public static Method findGetter(Class cls, String prop, boolean mustExist) {
|
||||
Method m = getGetterMethod(cls, prop);
|
||||
if (m != null) {
|
||||
return m;
|
||||
}
|
||||
prop = StringUtils.capitalize(prop);
|
||||
String name = "get" + prop;
|
||||
Method m;
|
||||
try {
|
||||
// this algorithm searches for a get<prop> or is<prop> method in
|
||||
// a breadth-first manner.
|
||||
|
@ -62,12 +141,15 @@ public class Reflection {
|
|||
c = c.getSuperclass()) {
|
||||
m = getDeclaredMethod(c, name, null);
|
||||
if (m != null) {
|
||||
setGetterMethod(cls, prop, m);
|
||||
return m;
|
||||
} else {
|
||||
m = getDeclaredMethod(c, "is" + prop, null);
|
||||
if (m != null && (m.getReturnType() == boolean.class
|
||||
|| m.getReturnType() == Boolean.class))
|
||||
|| m.getReturnType() == Boolean.class)) {
|
||||
setGetterMethod(cls, prop, m);
|
||||
return m;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
@ -95,14 +177,19 @@ public class Reflection {
|
|||
*/
|
||||
public static Method findSetter(Class cls, String prop, Class param,
|
||||
boolean mustExist) {
|
||||
Method m = getSetterMethod(cls, prop);
|
||||
if (m != null) {
|
||||
return m;
|
||||
}
|
||||
String name = "set" + StringUtils.capitalize(prop);
|
||||
Method m;
|
||||
try {
|
||||
for (Class c = cls; c != null && c != Object.class;
|
||||
c = c.getSuperclass()) {
|
||||
m = getDeclaredMethod(c, name, param);
|
||||
if (m != null)
|
||||
if (m != null) {
|
||||
setSetterMethod(cls, prop, m);
|
||||
return m;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new GeneralException(e);
|
||||
|
@ -774,10 +861,14 @@ public class Reflection {
|
|||
public static Set<String> getBeanStylePropertyNames(Class c) {
|
||||
if (c == null)
|
||||
return Collections.EMPTY_SET;
|
||||
Set<String> result = beanPropertiesNameCache.get(c);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
Method[] methods = c.getMethods();
|
||||
if (methods == null || methods.length < 2)
|
||||
return Collections.EMPTY_SET;
|
||||
Set<String> result = new TreeSet<String>();
|
||||
/*Set<String>*/ result = new TreeSet<String>();
|
||||
for (Method m : methods) {
|
||||
if (m.getName().startsWith("get")) {
|
||||
if (!canReflect(m))
|
||||
|
@ -795,6 +886,7 @@ public class Reflection {
|
|||
}
|
||||
}
|
||||
}
|
||||
beanPropertiesNameCache.put(c, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,23 +31,26 @@ import java.util.Map;
|
|||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import javax.transaction.Status;
|
||||
import javax.transaction.Synchronization;
|
||||
import javax.transaction.Transaction;
|
||||
import javax.transaction.TransactionManager;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.collections.set.MapBackedSet;
|
||||
import org.apache.openjpa.conf.OpenJPAConfiguration;
|
||||
import org.apache.openjpa.conf.OpenJPAVersion;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.openjpa.conf.BrokerValue;
|
||||
import org.apache.openjpa.conf.OpenJPAConfiguration;
|
||||
import org.apache.openjpa.conf.OpenJPAConfigurationImpl;
|
||||
import org.apache.openjpa.conf.OpenJPAVersion;
|
||||
import org.apache.openjpa.datacache.DataCacheStoreManager;
|
||||
import org.apache.openjpa.ee.ManagedRuntime;
|
||||
import org.apache.openjpa.enhance.ManagedClassSubclasser;
|
||||
import org.apache.openjpa.enhance.PCRegistry;
|
||||
import org.apache.openjpa.enhance.PersistenceCapable;
|
||||
import org.apache.openjpa.enhance.ManagedClassSubclasser;
|
||||
import org.apache.openjpa.enhance.Reflection;
|
||||
import org.apache.openjpa.event.BrokerFactoryEvent;
|
||||
import org.apache.openjpa.event.RemoteCommitEventManager;
|
||||
import org.apache.openjpa.lib.conf.Configuration;
|
||||
|
@ -55,9 +58,7 @@ import org.apache.openjpa.lib.conf.Configurations;
|
|||
import org.apache.openjpa.lib.log.Log;
|
||||
import org.apache.openjpa.lib.util.J2DoPrivHelper;
|
||||
import org.apache.openjpa.lib.util.Localizer;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import org.apache.openjpa.lib.util.concurrent.ConcurrentReferenceHashSet;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import org.apache.openjpa.meta.MetaDataRepository;
|
||||
import org.apache.openjpa.util.GeneralException;
|
||||
import org.apache.openjpa.util.InvalidStateException;
|
||||
|
@ -410,7 +411,7 @@ public abstract class AbstractBrokerFactory
|
|||
PCRegistry.removeRegisterClassListener
|
||||
(_conf.getMetaDataRepositoryInstance());
|
||||
}
|
||||
|
||||
Reflection.flushCaches(_pcClassLoaders);
|
||||
_conf.close();
|
||||
_closed = true;
|
||||
Log log = _conf.getLog(OpenJPAConfiguration.LOG_RUNTIME);
|
||||
|
|
Loading…
Reference in New Issue