Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

lighthouse-854 #259

Closed
wants to merge 1 commit into from

2 participants

Miklos Gyorfi Morten Kjetland
Miklos Gyorfi

Unsychronized internal cache in Binding -, solution new caching method, and immutable BeanWrapper and Property info.

Miklos Gyorfi gyorfimi lighthouse-854
Unsychronized internal cache in Binding -, solution new caching method, and immutable BeanWrapper and Property info.
90c9762
Miklos Gyorfi

I've renewed #235 due to requirements commented in that pull.

Morten Kjetland
Collaborator

Thanks a lot - it's merged

Morten Kjetland mbknor closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jun 8, 2011
  1. Miklos Gyorfi

    lighthouse-854

    gyorfimi authored
    Unsychronized internal cache in Binding -, solution new caching method, and immutable BeanWrapper and Property info.
This page is out of date. Refresh to see the latest.
73 framework/src/play/data/binding/BeanWrapper.java
View
@@ -8,6 +8,8 @@
import play.classloading.enhancers.PropertiesEnhancer.PlayPropertyAccessor;
import play.exceptions.UnexpectedException;
import play.utils.Utils;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
/**
* Parameters map to POJO binder.
@@ -16,29 +18,62 @@
final static int notwritableField = Modifier.FINAL | Modifier.NATIVE | Modifier.STATIC;
final static int notaccessibleMethod = Modifier.NATIVE | Modifier.STATIC;
+ final static ConcurrentMap<Class<?>, BeanWrapper> beanWrapperCache = new ConcurrentHashMap<Class<?>, BeanWrapper>();
- private Class<?> beanClass;
+ private final Class<?> beanClass;
/**
* a cache for our properties and setters
*/
private Map<String, Property> wrappers = new HashMap<String, Property>();
- BeanWrapper(Class<?> forClass) {
+ private BeanWrapper(Class<?> forClass) {
if (Logger.isTraceEnabled()) {
Logger.trace("Bean wrapper for class %s", forClass.getName());
}
this.beanClass = forClass;
}
+
+ /**
+ * Generator method - uses thread-safe cache
+ *
+ * @param forClass the class to be wrapped
+ * @return the wrapper
+ */
+
public static BeanWrapper forClass(Class<?> forClass) {
- BeanWrapper beanWrapper = new JavaBeanWrapper(forClass);
- for (Class<?> intf: forClass.getInterfaces()) {
+ final BeanWrapper wrapper = beanWrapperCache.get(forClass);
+ if (wrapper == null) {
+ final BeanWrapper newWrapper = BeanWrapper.generateForClass(forClass);
+ /*
+ Sometimes it create an instance, but it won't be used, as
+ somebody has generated another yet, and put it into the cache
+ */
+ final BeanWrapper cachedWrapper = beanWrapperCache.putIfAbsent(forClass, newWrapper);
+
+ return cachedWrapper == null ? newWrapper : cachedWrapper;
+ /*
+ It is not thread-safe consistent to get then use put later, putIfAbsent makes it consistent,
+ it returns always the same value.
+ */
+ }
+ return wrapper;
+ }
+
+ private static BeanWrapper generateForClass(Class<?> forClass) {
+ BeanWrapper beanWrapper = null;
+ for (Class<?> intf : forClass.getInterfaces()) {
if ("scala.ScalaObject".equals(intf.getName())) {
beanWrapper = new ScalaBeanWrapper(forClass);
break;
}
}
+
+ if (beanWrapper == null) {
+ beanWrapper = new JavaBeanWrapper(forClass);
+ }
+
beanWrapper.registerSetters(forClass);
beanWrapper.registerFields(forClass);
return beanWrapper;
@@ -190,14 +225,17 @@ private void registerSetters(Class<?> clazz) {
}
}
- public static class Property {
- private Annotation[] annotations;
- private Method setter;
- private Field field;
- private Class<?> type;
- private Type genericType;
- private String name;
- private String[] profiles;
+ /**
+ * Immutable property wrapper
+ */
+ public static class Property {
+ final private Annotation[] annotations;
+ final private Method setter;
+ final private Field field;
+ final private Class<?> type;
+ final private Type genericType;
+ final private String name;
+ final private String[] profiles;
Property(String propertyName, Method setterMethod) {
name = propertyName;
@@ -205,7 +243,8 @@ private void registerSetters(Class<?> clazz) {
type = setter.getParameterTypes()[0];
annotations = setter.getAnnotations();
genericType = setter.getGenericParameterTypes()[0];
- setProfiles(this.annotations);
+ field = null;
+ profiles = createProfiles(this.annotations);
}
Property(Field field) {
@@ -215,18 +254,20 @@ private void registerSetters(Class<?> clazz) {
type = field.getType();
annotations = field.getAnnotations();
genericType = field.getGenericType();
- setProfiles(this.annotations);
+ setter = null;
+ profiles = createProfiles(this.annotations);
}
- public void setProfiles(Annotation[] annotations) {
+ private static String[] createProfiles(Annotation[] annotations) {
if (annotations != null) {
for (Annotation annotation : annotations) {
if (annotation.annotationType().equals(NoBinding.class)) {
NoBinding as = ((NoBinding) annotation);
- profiles = as.value();
+ return as.value();
}
}
}
+ return null;
}
public void setValue(Object instance, Object value) {
8 framework/src/play/data/binding/Binder.java
View
@@ -48,15 +48,11 @@
supportedTypes.put(clazz, typeBinder);
}
- static Map<Class<?>, BeanWrapper> beanwrappers = new HashMap<Class<?>, BeanWrapper>();
static BeanWrapper getBeanWrapper(Class<?> clazz) {
- if (!beanwrappers.containsKey(clazz)) {
- BeanWrapper beanwrapper = BeanWrapper.forClass(clazz);
- beanwrappers.put(clazz, beanwrapper);
- }
- return beanwrappers.get(clazz);
+ return BeanWrapper.forClass(clazz);
}
+
public final static Object MISSING = new Object();
public final static Object NO_BINDING = new Object();
Something went wrong with that request. Please try again.