Author: markt
Date: Thu Sep  8 10:57:19 2011
New Revision: 1166620

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

Modified:
    tomcat/trunk/java/org/apache/catalina/core/DefaultInstanceManager.java

Modified: tomcat/trunk/java/org/apache/catalina/core/DefaultInstanceManager.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/DefaultInstanceManager.java?rev=1166620&r1=1166619&r2=1166620&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/DefaultInstanceManager.java 
(original)
+++ tomcat/trunk/java/org/apache/catalina/core/DefaultInstanceManager.java Thu 
Sep  8 10:57:19 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-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to