Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

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 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
mbknor commented

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

Showing 1 unique commit by 1 author.

Jun 08, 2011
Miklos Gyorfi lighthouse-854
Unsychronized internal cache in Binding -, solution new caching method, and immutable BeanWrapper and Property info.
90c9762
This page is out of date. Refresh to see the latest.
73  framework/src/play/data/binding/BeanWrapper.java
@@ -8,6 +8,8 @@
8 8
 import play.classloading.enhancers.PropertiesEnhancer.PlayPropertyAccessor;
9 9
 import play.exceptions.UnexpectedException;
10 10
 import play.utils.Utils;
  11
+import java.util.concurrent.ConcurrentHashMap;
  12
+import java.util.concurrent.ConcurrentMap;
11 13
 
12 14
 /**
13 15
  * Parameters map to POJO binder.
@@ -16,29 +18,62 @@
16 18
 
17 19
     final static int notwritableField = Modifier.FINAL | Modifier.NATIVE | Modifier.STATIC;
18 20
     final static int notaccessibleMethod = Modifier.NATIVE | Modifier.STATIC;
  21
+    final static ConcurrentMap<Class<?>, BeanWrapper> beanWrapperCache = new ConcurrentHashMap<Class<?>, BeanWrapper>();
19 22
 
20  
-    private Class<?> beanClass;
  23
+    private final Class<?> beanClass;
21 24
 
22 25
     /**
23 26
      * a cache for our properties and setters
24 27
      */
25 28
     private Map<String, Property> wrappers = new HashMap<String, Property>();
26 29
 
27  
-    BeanWrapper(Class<?> forClass) {
  30
+    private BeanWrapper(Class<?> forClass) {
28 31
         if (Logger.isTraceEnabled()) {
29 32
             Logger.trace("Bean wrapper for class %s", forClass.getName());
30 33
         }
31 34
         this.beanClass = forClass;
32 35
     }
33 36
 
  37
+
  38
+    /**
  39
+     * Generator method - uses thread-safe cache
  40
+     *
  41
+     * @param forClass the class to be wrapped
  42
+     * @return the wrapper
  43
+     */
  44
+
34 45
     public static BeanWrapper forClass(Class<?> forClass) {
35  
-        BeanWrapper beanWrapper = new JavaBeanWrapper(forClass);
36  
-        for (Class<?> intf: forClass.getInterfaces()) {
  46
+        final BeanWrapper wrapper = beanWrapperCache.get(forClass);
  47
+        if (wrapper == null) {
  48
+            final BeanWrapper newWrapper = BeanWrapper.generateForClass(forClass);
  49
+            /*
  50
+              Sometimes it create an instance, but it won't be used, as
  51
+              somebody has generated another yet, and put it into the cache
  52
+            */
  53
+            final BeanWrapper cachedWrapper = beanWrapperCache.putIfAbsent(forClass, newWrapper);
  54
+
  55
+            return cachedWrapper == null ? newWrapper : cachedWrapper;
  56
+            /*
  57
+            It is not thread-safe consistent to get then use put later, putIfAbsent makes it consistent,
  58
+            it returns always the same value.
  59
+            */
  60
+        }
  61
+        return wrapper;
  62
+    }
  63
+
  64
+    private static BeanWrapper generateForClass(Class<?> forClass) {
  65
+        BeanWrapper beanWrapper = null;
  66
+        for (Class<?> intf : forClass.getInterfaces()) {
37 67
             if ("scala.ScalaObject".equals(intf.getName())) {
38 68
                 beanWrapper = new ScalaBeanWrapper(forClass);
39 69
                 break;
40 70
             }
41 71
         }
  72
+
  73
+        if (beanWrapper == null) {
  74
+            beanWrapper = new JavaBeanWrapper(forClass);
  75
+        }
  76
+
42 77
         beanWrapper.registerSetters(forClass);
43 78
         beanWrapper.registerFields(forClass);
44 79
         return beanWrapper;
@@ -190,14 +225,17 @@ private void registerSetters(Class<?> clazz) {
190 225
         }
191 226
     }
192 227
 
193  
-    public static class Property {
194  
-        private Annotation[] annotations;
195  
-        private Method setter;
196  
-        private Field field;
197  
-        private Class<?> type;
198  
-        private Type genericType;
199  
-        private String name;
200  
-        private String[] profiles;
  228
+     /**
  229
+      * Immutable property wrapper
  230
+      */
  231
+     public static class Property {
  232
+        final private Annotation[] annotations;
  233
+        final private Method setter;
  234
+        final private Field field;
  235
+        final private Class<?> type;
  236
+        final private Type genericType;
  237
+        final private String name;
  238
+        final private String[] profiles;
201 239
 
202 240
         Property(String propertyName, Method setterMethod) {
203 241
             name = propertyName;
@@ -205,7 +243,8 @@ private void registerSetters(Class<?> clazz) {
205 243
             type = setter.getParameterTypes()[0];
206 244
             annotations = setter.getAnnotations();
207 245
             genericType = setter.getGenericParameterTypes()[0];
208  
-            setProfiles(this.annotations);
  246
+            field = null;
  247
+            profiles = createProfiles(this.annotations);
209 248
         }
210 249
 
211 250
         Property(Field field) {
@@ -215,18 +254,20 @@ private void registerSetters(Class<?> clazz) {
215 254
             type = field.getType();
216 255
             annotations = field.getAnnotations();
217 256
             genericType = field.getGenericType();
218  
-            setProfiles(this.annotations);
  257
+            setter = null;
  258
+            profiles = createProfiles(this.annotations);
219 259
         }
220 260
 
221  
-        public void setProfiles(Annotation[] annotations) {
  261
+        private static String[] createProfiles(Annotation[] annotations) {
222 262
             if (annotations != null) {
223 263
                 for (Annotation annotation : annotations) {
224 264
                     if (annotation.annotationType().equals(NoBinding.class)) {
225 265
                         NoBinding as = ((NoBinding) annotation);
226  
-                        profiles = as.value();
  266
+                        return as.value();
227 267
                     }
228 268
                 }
229 269
             }
  270
+            return null;
230 271
         }
231 272
 
232 273
         public void setValue(Object instance, Object value) {
8  framework/src/play/data/binding/Binder.java
@@ -48,15 +48,11 @@
48 48
         supportedTypes.put(clazz, typeBinder);
49 49
     }
50 50
 
51  
-    static Map<Class<?>, BeanWrapper> beanwrappers = new HashMap<Class<?>, BeanWrapper>();
52 51
 
53 52
     static BeanWrapper getBeanWrapper(Class<?> clazz) {
54  
-        if (!beanwrappers.containsKey(clazz)) {
55  
-            BeanWrapper beanwrapper = BeanWrapper.forClass(clazz);
56  
-            beanwrappers.put(clazz, beanwrapper);
57  
-        }
58  
-        return beanwrappers.get(clazz);
  53
+        return BeanWrapper.forClass(clazz);
59 54
     }
  55
+
60 56
     public final static Object MISSING = new Object();
61 57
     public final static Object NO_BINDING = new Object();
62 58
 
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.