init/destroy methods get processed in the order of declaration at each hierarchy level (SPR-6344); process DestructionAwareBeanPostProcessors in common post-processor order; aligned metadata retrieval code

This commit is contained in:
Juergen Hoeller 2009-11-19 23:49:10 +00:00
parent 4375b9c89a
commit 3b9605bc57
3 changed files with 114 additions and 95 deletions

View File

@ -303,13 +303,22 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
} }
private InjectionMetadata findAutowiringMetadata(final Class clazz) { private InjectionMetadata findAutowiringMetadata(Class clazz) {
// Quick check on the concurrent map first, with minimal locking. // Quick check on the concurrent map first, with minimal locking.
InjectionMetadata metadata = this.injectionMetadataCache.get(clazz); InjectionMetadata metadata = this.injectionMetadataCache.get(clazz);
if (metadata == null) { if (metadata == null) {
synchronized (this.injectionMetadataCache) { synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(clazz); metadata = this.injectionMetadataCache.get(clazz);
if (metadata == null) { if (metadata == null) {
metadata = buildAutowiringMetadata(clazz);
this.injectionMetadataCache.put(clazz, metadata);
}
}
}
return metadata;
}
private InjectionMetadata buildAutowiringMetadata(Class clazz) {
LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<InjectionMetadata.InjectedElement>(); LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<InjectionMetadata.InjectedElement>();
Class<?> targetClass = clazz; Class<?> targetClass = clazz;
@ -352,12 +361,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
} }
while (targetClass != null && targetClass != Object.class); while (targetClass != null && targetClass != Object.class);
metadata = new InjectionMetadata(clazz, elements); return new InjectionMetadata(clazz, elements);
this.injectionMetadataCache.put(clazz, metadata);
}
}
}
return metadata;
} }
private Annotation findAutowiredAnnotation(AccessibleObject ao) { private Annotation findAutowiredAnnotation(AccessibleObject ao) {

View File

@ -25,8 +25,10 @@ import java.lang.reflect.Method;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.util.Collection; import java.util.Collection;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
@ -118,24 +120,7 @@ public class InitDestroyAnnotationBeanPostProcessor
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class beanType, String beanName) { public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class beanType, String beanName) {
if (beanType != null) { if (beanType != null) {
LifecycleMetadata metadata = findLifecycleMetadata(beanType); LifecycleMetadata metadata = findLifecycleMetadata(beanType);
for (Iterator<LifecycleElement> it = metadata.getInitMethods().iterator(); it.hasNext();) { metadata.checkConfigMembers(beanDefinition);
String methodIdentifier = it.next().getIdentifier();
if (!beanDefinition.isExternallyManagedInitMethod(methodIdentifier)) {
beanDefinition.registerExternallyManagedInitMethod(methodIdentifier);
}
else {
it.remove();
}
}
for (Iterator<LifecycleElement> it = metadata.getDestroyMethods().iterator(); it.hasNext();) {
String methodIdentifier = it.next().getIdentifier();
if (!beanDefinition.isExternallyManagedDestroyMethod(methodIdentifier)) {
beanDefinition.registerExternallyManagedDestroyMethod(methodIdentifier);
}
else {
it.remove();
}
}
} }
} }
@ -197,30 +182,41 @@ public class InitDestroyAnnotationBeanPostProcessor
return metadata; return metadata;
} }
private LifecycleMetadata buildLifecycleMetadata(final Class clazz) { private LifecycleMetadata buildLifecycleMetadata(Class clazz) {
final LifecycleMetadata newMetadata = new LifecycleMetadata();
final boolean debug = logger.isDebugEnabled(); final boolean debug = logger.isDebugEnabled();
ReflectionUtils.doWithMethods(clazz, new ReflectionUtils.MethodCallback() { LinkedList<LifecycleElement> initMethods = new LinkedList<LifecycleElement>();
public void doWith(Method method) { LinkedList<LifecycleElement> destroyMethods = new LinkedList<LifecycleElement>();
if (initAnnotationType != null) { Class<?> targetClass = clazz;
if (method.getAnnotation(initAnnotationType) != null) {
newMetadata.addInitMethod(method); do {
LinkedList<LifecycleElement> currInitMethods = new LinkedList<LifecycleElement>();
LinkedList<LifecycleElement> currDestroyMethods = new LinkedList<LifecycleElement>();
for (Method method : targetClass.getDeclaredMethods()) {
if (this.initAnnotationType != null) {
if (method.getAnnotation(this.initAnnotationType) != null) {
LifecycleElement element = new LifecycleElement(method);
currInitMethods.add(element);
if (debug) { if (debug) {
logger.debug("Found init method on class [" + clazz.getName() + "]: " + method); logger.debug("Found init method on class [" + clazz.getName() + "]: " + method);
} }
} }
} }
if (destroyAnnotationType != null) { if (this.destroyAnnotationType != null) {
if (method.getAnnotation(destroyAnnotationType) != null) { if (method.getAnnotation(this.destroyAnnotationType) != null) {
newMetadata.addDestroyMethod(method); currDestroyMethods.add(new LifecycleElement(method));
if (debug) { if (debug) {
logger.debug("Found destroy method on class [" + clazz.getName() + "]: " + method); logger.debug("Found destroy method on class [" + clazz.getName() + "]: " + method);
} }
} }
} }
} }
}); initMethods.addAll(0, currInitMethods);
return newMetadata; destroyMethods.addAll(currDestroyMethods);
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return new LifecycleMetadata(clazz, initMethods, destroyMethods);
} }
@ -242,19 +238,49 @@ public class InitDestroyAnnotationBeanPostProcessor
*/ */
private class LifecycleMetadata { private class LifecycleMetadata {
private final LinkedList<LifecycleElement> initMethods = new LinkedList<LifecycleElement>(); private final Set<LifecycleElement> initMethods;
private final LinkedList<LifecycleElement> destroyMethods = new LinkedList<LifecycleElement>(); private final Set<LifecycleElement> destroyMethods;
public void addInitMethod(Method method) { public LifecycleMetadata(Class targetClass, Collection<LifecycleElement> initMethods,
LifecycleElement element = new LifecycleElement(method); Collection<LifecycleElement> destroyMethods) {
if (!this.initMethods.contains(element)) {
this.initMethods.addFirst(element); this.initMethods = new LinkedHashSet<LifecycleElement>();
for (LifecycleElement element : initMethods) {
if (logger.isDebugEnabled()) {
logger.debug("Found init method on class [" + targetClass.getName() + "]: " + element);
}
this.initMethods.add(element);
}
this.destroyMethods = new LinkedHashSet<LifecycleElement>();
for (LifecycleElement element : destroyMethods) {
if (logger.isDebugEnabled()) {
logger.debug("Found destroy method on class [" + targetClass.getName() + "]: " + element);
}
this.destroyMethods.add(element);
} }
} }
public Collection<LifecycleElement> getInitMethods() { public void checkConfigMembers(RootBeanDefinition beanDefinition) {
return this.initMethods; for (Iterator<LifecycleElement> it = this.initMethods.iterator(); it.hasNext();) {
String methodIdentifier = it.next().getIdentifier();
if (!beanDefinition.isExternallyManagedInitMethod(methodIdentifier)) {
beanDefinition.registerExternallyManagedInitMethod(methodIdentifier);
}
else {
it.remove();
}
}
for (Iterator<LifecycleElement> it = this.destroyMethods.iterator(); it.hasNext();) {
String methodIdentifier = it.next().getIdentifier();
if (!beanDefinition.isExternallyManagedDestroyMethod(methodIdentifier)) {
beanDefinition.registerExternallyManagedDestroyMethod(methodIdentifier);
}
else {
it.remove();
}
}
} }
public void invokeInitMethods(Object target, String beanName) throws Throwable { public void invokeInitMethods(Object target, String beanName) throws Throwable {
@ -269,17 +295,6 @@ public class InitDestroyAnnotationBeanPostProcessor
} }
} }
public void addDestroyMethod(Method method) {
LifecycleElement element = new LifecycleElement(method);
if (!this.destroyMethods.contains(element)) {
this.destroyMethods.addLast(element);
}
}
public Collection<LifecycleElement> getDestroyMethods() {
return this.destroyMethods;
}
public void invokeDestroyMethods(Object target, String beanName) throws Throwable { public void invokeDestroyMethods(Object target, String beanName) throws Throwable {
if (!this.destroyMethods.isEmpty()) { if (!this.destroyMethods.isEmpty()) {
boolean debug = logger.isDebugEnabled(); boolean debug = logger.isDebugEnabled();

View File

@ -162,8 +162,8 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
public void destroy() { public void destroy() {
if (this.beanPostProcessors != null && !this.beanPostProcessors.isEmpty()) { if (this.beanPostProcessors != null && !this.beanPostProcessors.isEmpty()) {
for (int i = this.beanPostProcessors.size() - 1; i >= 0; i--) { for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
this.beanPostProcessors.get(i).postProcessBeforeDestruction(this.bean, this.beanName); processor.postProcessBeforeDestruction(this.bean, this.beanName);
} }
} }