You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2011/09/08 12:59:04 UTC

svn commit: r1166622 - in /tomcat/tc7.0.x/trunk: ./ java/org/apache/catalina/core/DefaultInstanceManager.java

Author: markt
Date: Thu Sep  8 10:59:04 2011
New Revision: 1166622

URL: http://svn.apache.org/viewvc?rev=1166622&view=rev
Log:
Add caching of postConstruct and preDestroy annotations

Modified:
    tomcat/tc7.0.x/trunk/   (props changed)
    tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/DefaultInstanceManager.java

Propchange: tomcat/tc7.0.x/trunk/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Thu Sep  8 10:59:04 2011
@@ -1 +1 @@
-/tomcat/trunk:1156171,1156276,1156304,1156530,1156602,1157015,1157018,1157151,1157198,1157204,1157810,1157832,1157834,1157847,1157908,1157939,1158155,1158160,1158176,1158195,1158198-1158199,1158227,1158331,1158334-1158335,1158426,1160347,1160592,1160611,1160619,1160626,1160639,1160652,1160720-1160721,1160772,1160774,1160776,1161303,1161310,1161322,1161339,1161486,1161540,1161549,1161584,1162082,1162149,1162169,1162721,1162769,1162836,1162932,1163630,1164419,1164438,1164469,1164480,1164567,1165234,1165247-1165248,1165253,1165273,1165282,1165309,1165331,1165338,1165347,1165360-1165361,1165367-1165368,1165602,1165608,1165677,1165693,1165721,1165723,1165728,1165730,1165738,1165746,1165765,1165777,1165918,1165921,1166077,1166150-1166151,1166290,1166366
+/tomcat/trunk:1156171,1156276,1156304,1156530,1156602,1157015,1157018,1157151,1157198,1157204,1157810,1157832,1157834,1157847,1157908,1157939,1158155,1158160,1158176,1158195,1158198-1158199,1158227,1158331,1158334-1158335,1158426,1160347,1160592,1160611,1160619,1160626,1160639,1160652,1160720-1160721,1160772,1160774,1160776,1161303,1161310,1161322,1161339,1161486,1161540,1161549,1161584,1162082,1162149,1162169,1162721,1162769,1162836,1162932,1163630,1164419,1164438,1164469,1164480,1164567,1165234,1165247-1165248,1165253,1165273,1165282,1165309,1165331,1165338,1165347,1165360-1165361,1165367-1165368,1165602,1165608,1165677,1165693,1165721,1165723,1165728,1165730,1165738,1165746,1165765,1165777,1165918,1165921,1166077,1166150-1166151,1166290,1166366,1166620

Modified: tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/DefaultInstanceManager.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/DefaultInstanceManager.java?rev=1166622&r1=1166621&r2=1166622&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/DefaultInstanceManager.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/DefaultInstanceManager.java Thu Sep  8 10:59:04 2011
@@ -141,6 +141,7 @@ public class DefaultInstanceManager impl
     private Object newInstance(Object instance, Class<?> clazz) throws IllegalAccessException, InvocationTargetException, NamingException {
         if (!ignoreAnnotations) {
             Map<String, String> injections = injectionMap.get(clazz.getName());
+            populateAnnotationsCache(clazz, injections);
             processAnnotations(instance, injections);
             postConstruct(instance, clazz);
         }
@@ -170,41 +171,18 @@ public class DefaultInstanceManager impl
             postConstruct(instance, superClass);
         }
 
-        Method[] methods = null;
-        if (Globals.IS_SECURITY_ENABLED) {
-            methods = AccessController.doPrivileged(
-                    new PrivilegedAction<Method[]>(){
-                @Override
-                public Method[] run(){
-                    return clazz.getDeclaredMethods();
-                }
-            });
-        } else {
-            methods = clazz.getDeclaredMethods();
-        }
-        Method postConstruct = null;
-        for (Method method : methods) {
-            if (method.isAnnotationPresent(PostConstruct.class)) {
-                if ((postConstruct != null)
-                        || (method.getParameterTypes().length != 0)
-                        || (Modifier.isStatic(method.getModifiers()))
-                        || (method.getExceptionTypes().length > 0)
-                        || (!method.getReturnType().getName().equals("void"))) {
-                    throw new IllegalArgumentException("Invalid PostConstruct annotation");
-                }
-                postConstruct = method;
-            }
-        }
-
         // At the end the postconstruct annotated
         // method is invoked
-        if (postConstruct != null) {
-            boolean accessibility = postConstruct.isAccessible();
-            postConstruct.setAccessible(true);
-            postConstruct.invoke(instance);
-            postConstruct.setAccessible(accessibility);
+        List<AnnotationCacheEntry> annotations = annotationCache.get(clazz);
+        for (AnnotationCacheEntry entry : annotations) {
+            if (entry.getType() == AnnotationCacheEntryType.POST_CONSTRUCT) {
+                Method postConstruct = (Method) entry.getAccessibleObject();
+                boolean accessibility = postConstruct.isAccessible();
+                postConstruct.setAccessible(true);
+                postConstruct.invoke(instance);
+                postConstruct.setAccessible(accessibility);
+            }
         }
-
     }
 
 
@@ -224,64 +202,42 @@ public class DefaultInstanceManager impl
             preDestroy(instance, superClass);
         }
 
-        Method[] methods;
-        if (Globals.IS_SECURITY_ENABLED) {
-            methods = AccessController.doPrivileged(
-                    new PrivilegedAction<Method[]>(){
-                @Override
-                public Method[] run(){
-                    return clazz.getDeclaredMethods();
-                }
-            });
-        } else {
-            methods = clazz.getDeclaredMethods();
-        }
-        Method preDestroy = null;
-        for (Method method : methods) {
-            if (method.isAnnotationPresent(PreDestroy.class)) {
-                if ((method.getParameterTypes().length != 0)
-                        || (Modifier.isStatic(method.getModifiers()))
-                        || (method.getExceptionTypes().length > 0)
-                        || (!method.getReturnType().getName().equals("void"))) {
-                    throw new IllegalArgumentException("Invalid PreDestroy annotation");
-                }
-                preDestroy = method;
-                break;
-            }
-        }
-
         // At the end the postconstruct annotated
         // method is invoked
-        if (preDestroy != null) {
-            boolean accessibility = preDestroy.isAccessible();
-            preDestroy.setAccessible(true);
-            preDestroy.invoke(instance);
-            preDestroy.setAccessible(accessibility);
+        List<AnnotationCacheEntry> annotations = annotationCache.get(clazz);
+        for (AnnotationCacheEntry entry : annotations) {
+            if (entry.getType() == AnnotationCacheEntryType.PRE_DESTROY) {
+                Method preDestroy = (Method) entry.getAccessibleObject();
+                boolean accessibility = preDestroy.isAccessible();
+                preDestroy.setAccessible(true);
+                preDestroy.invoke(instance);
+                preDestroy.setAccessible(accessibility);
+            }
         }
-
     }
 
 
     /**
-     * Inject resources in specified instance.
+     * Make sure that the annotations cache has been populated for the provided
+     * class.
      *
-     * @param instance   instance to inject into
-     * @param injections map of injections for this class from xml deployment descriptor
+     * @param clazz         clazz to populate annotations for
+     * @param injections    map of injections for this class from xml deployment
+     *                      descriptor
      * @throws IllegalAccessException       if injection target is inaccessible
      * @throws javax.naming.NamingException if value cannot be looked up in jndi
      * @throws java.lang.reflect.InvocationTargetException
      *                                      if injection fails
      */
-    protected void processAnnotations(Object instance, Map<String, String> injections)
-            throws IllegalAccessException, InvocationTargetException, NamingException {
+    protected void populateAnnotationsCache(Class<?> clazz,
+            Map<String, String> injections) throws IllegalAccessException,
+            InvocationTargetException, NamingException {
 
         if (context == null) {
             // No resource injection
             return;
         }
 
-        Class<?> clazz = instance.getClass();
-        
         while (clazz != null) {
             List<AnnotationCacheEntry> annotations = annotationCache.get(clazz);
             if (annotations == null) {
@@ -302,43 +258,37 @@ public class DefaultInstanceManager impl
                 }
                 for (Field field : fields) {
                     if (injections != null && injections.containsKey(field.getName())) {
-                        lookupFieldResource(context, instance, field,
-                                injections.get(field.getName()), clazz);
                         annotations.add(new AnnotationCacheEntry(field,
-                                injections.get(field.getName())));
+                                injections.get(field.getName()),
+                                AnnotationCacheEntryType.FIELD));
                     } else if (field.isAnnotationPresent(Resource.class)) {
                         Resource annotation = field.getAnnotation(Resource.class);
-                        lookupFieldResource(context, instance, field,
-                                annotation.name(), clazz);
                         annotations.add(new AnnotationCacheEntry(field,
-                                annotation.name()));
+                                annotation.name(),
+                                AnnotationCacheEntryType.FIELD));
                     } else if (field.isAnnotationPresent(EJB.class)) {
                         EJB annotation = field.getAnnotation(EJB.class);
-                        lookupFieldResource(context, instance, field,
-                                annotation.name(), clazz);
                         annotations.add(new AnnotationCacheEntry(field,
-                                annotation.name()));
+                                annotation.name(),
+                                AnnotationCacheEntryType.FIELD));
                     } else if (field.isAnnotationPresent(WebServiceRef.class)) {
                         WebServiceRef annotation =
                                 field.getAnnotation(WebServiceRef.class);
-                        lookupFieldResource(context, instance, field,
-                                annotation.name(), clazz);
                         annotations.add(new AnnotationCacheEntry(field,
-                                annotation.name()));
+                                annotation.name(),
+                                AnnotationCacheEntryType.FIELD));
                     } else if (field.isAnnotationPresent(PersistenceContext.class)) {
                         PersistenceContext annotation =
                                 field.getAnnotation(PersistenceContext.class);
-                        lookupFieldResource(context, instance, field,
-                                annotation.name(), clazz);
                         annotations.add(new AnnotationCacheEntry(field,
-                                annotation.name()));
+                                annotation.name(),
+                                AnnotationCacheEntryType.FIELD));
                     } else if (field.isAnnotationPresent(PersistenceUnit.class)) {
                         PersistenceUnit annotation =
                                 field.getAnnotation(PersistenceUnit.class);
-                        lookupFieldResource(context, instance, field,
-                                annotation.name(), clazz);
                         annotations.add(new AnnotationCacheEntry(field,
-                                annotation.name()));
+                                annotation.name(),
+                                AnnotationCacheEntryType.FIELD));
                     }
                 }
         
@@ -356,60 +306,121 @@ public class DefaultInstanceManager impl
                 } else {
                     methods = clazz.getDeclaredMethods();
                 }
+                Method postConstruct = null;
+                Method preDestroy = null;
                 for (Method method : methods) {
                     String methodName = method.getName();
                     if (injections != null && methodName.startsWith("set") && methodName.length() > 3) {
                         String fieldName = Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4);
                         if (injections.containsKey(fieldName)) {
-                            lookupMethodResource(context, instance, method,
-                                    injections.get(fieldName), clazz);
                             annotations.add(new AnnotationCacheEntry(method,
-                                    injections.get(method.getName())));
+                                    injections.get(method.getName()),
+                                    AnnotationCacheEntryType.FIELD));
                             break;
                         }
                     }
                     if (method.isAnnotationPresent(Resource.class)) {
                         Resource annotation = method.getAnnotation(Resource.class);
-                        lookupMethodResource(context, instance, method,
-                                annotation.name(), clazz);
                         annotations.add(new AnnotationCacheEntry(method,
-                                annotation.name()));
+                                annotation.name(),
+                                AnnotationCacheEntryType.FIELD));
                     } else if (method.isAnnotationPresent(EJB.class)) {
                         EJB annotation = method.getAnnotation(EJB.class);
-                        lookupMethodResource(context, instance, method,
-                                annotation.name(), clazz);
                         annotations.add(new AnnotationCacheEntry(method,
-                                annotation.name()));
+                                annotation.name(),
+                                AnnotationCacheEntryType.FIELD));
                     } else if (method.isAnnotationPresent(WebServiceRef.class)) {
                         WebServiceRef annotation =
                                 method.getAnnotation(WebServiceRef.class);
-                        lookupMethodResource(context, instance, method,
-                                annotation.name(), clazz);
                         annotations.add(new AnnotationCacheEntry(method,
-                                annotation.name()));
+                                annotation.name(),
+                                AnnotationCacheEntryType.FIELD));
                     } else if (method.isAnnotationPresent(PersistenceContext.class)) {
                         PersistenceContext annotation =
                                 method.getAnnotation(PersistenceContext.class);
-                        lookupMethodResource(context, instance, method,
-                                annotation.name(), clazz);
                         annotations.add(new AnnotationCacheEntry(method,
-                                annotation.name()));
+                                annotation.name(),
+                                AnnotationCacheEntryType.FIELD));
                     } else if (method.isAnnotationPresent(PersistenceUnit.class)) {
                         PersistenceUnit annotation =
                                 method.getAnnotation(PersistenceUnit.class);
-                        lookupMethodResource(context, instance, method,
-                                annotation.name(), clazz);
                         annotations.add(new AnnotationCacheEntry(method,
-                                annotation.name()));
+                                annotation.name(),
+                                AnnotationCacheEntryType.FIELD));
+                    }
+
+                    if (method.isAnnotationPresent(PostConstruct.class)) {
+                        if ((postConstruct != null) ||
+                                (method.getParameterTypes().length != 0) ||
+                                (Modifier.isStatic(method.getModifiers())) ||
+                                (method.getExceptionTypes().length > 0) ||
+                                (!method.getReturnType().getName().equals("void"))) {
+                            throw new IllegalArgumentException(
+                                    "Invalid PostConstruct annotation");
+                        }
+                        postConstruct = method;
+                    }
+                    
+                    if (method.isAnnotationPresent(PreDestroy.class)) {
+                        if ((preDestroy != null ||
+                                method.getParameterTypes().length != 0) ||
+                                (Modifier.isStatic(method.getModifiers())) ||
+                                (method.getExceptionTypes().length > 0) ||
+                                (!method.getReturnType().getName().equals("void"))) {
+                            throw new IllegalArgumentException(
+                                    "Invalid PreDestroy annotation");
+                        }
+                        preDestroy = method;
                     }
                 }
+                if (postConstruct != null) {
+                    annotations.add(new AnnotationCacheEntry(postConstruct,
+                            null, AnnotationCacheEntryType.POST_CONSTRUCT));
+                }
+                if (preDestroy != null) {
+                    annotations.add(new AnnotationCacheEntry(preDestroy,
+                            null, AnnotationCacheEntryType.PRE_DESTROY));
+                }
                 if (annotations.size() == 0) {
                     // Use common empty list to save memory 
                     annotations = Collections.emptyList();
                 }
                 annotationCache.put(clazz, annotations);
             } else {
-                for (AnnotationCacheEntry entry : annotations) {
+                // If the annotations for this class have been cached, the
+                // annotations for all the super classes will have been cachced
+                // as well
+                break;
+            }
+            clazz = clazz.getSuperclass();
+        }
+    }
+
+
+    /**
+     * Inject resources in specified instance.
+     *
+     * @param instance   instance to inject into
+     * @param injections map of injections for this class from xml deployment descriptor
+     * @throws IllegalAccessException       if injection target is inaccessible
+     * @throws javax.naming.NamingException if value cannot be looked up in jndi
+     * @throws java.lang.reflect.InvocationTargetException
+     *                                      if injection fails
+     */
+    protected void processAnnotations(Object instance, Map<String, String> injections)
+            throws IllegalAccessException, InvocationTargetException, NamingException {
+
+        if (context == null) {
+            // No resource injection
+            return;
+        }
+
+        Class<?> clazz = instance.getClass();
+        
+        while (clazz != null) {
+            List<AnnotationCacheEntry> annotations = annotationCache.get(clazz);
+            for (AnnotationCacheEntry entry : annotations) {
+                if (entry.getType() == AnnotationCacheEntryType.FIELD) {
                     if (entry.getAccessibleObject() instanceof Method) {
                         lookupMethodResource(context, instance,
                                 (Method) entry.getAccessibleObject(),
@@ -423,7 +434,6 @@ public class DefaultInstanceManager impl
             }
             clazz = clazz.getSuperclass();
         }
-
     }
 
 
@@ -585,11 +595,13 @@ public class DefaultInstanceManager impl
     private static final class AnnotationCacheEntry {
         private final AccessibleObject accessibleObject;
         private final String name;
+        private final AnnotationCacheEntryType type;
 
         public AnnotationCacheEntry(AccessibleObject accessibleObject,
-                String name) {
+                String name, AnnotationCacheEntryType type) {
             this.accessibleObject = accessibleObject;
             this.name = name;
+            this.type = type;
         }
 
         public AccessibleObject getAccessibleObject() {
@@ -599,5 +611,12 @@ public class DefaultInstanceManager impl
         public String getName() {
             return name;
         }
+        public AnnotationCacheEntryType getType() {
+            return type;
+        }
+    }
+
+    private static enum AnnotationCacheEntryType {
+        FIELD, POST_CONSTRUCT, PRE_DESTROY
     }
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org