SPR-6094: PostConstruct now processed top-down (base class first); @PreDestroy processed bottom-up (subclass first)

This commit is contained in:
Juergen Hoeller
2009-09-23 20:53:21 +00:00
parent 64bf3b74b5
commit d4c16e91df
2 changed files with 42 additions and 30 deletions

View File

@@ -21,10 +21,10 @@ import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.logging.Log;
@@ -119,18 +119,18 @@ public class InitDestroyAnnotationBeanPostProcessor
if (beanType != null) {
LifecycleMetadata metadata = findLifecycleMetadata(beanType);
for (Iterator<LifecycleElement> it = metadata.getInitMethods().iterator(); it.hasNext();) {
String methodName = calculateMethodIdentifierInHierarchy(it.next().getMethod());
if (!beanDefinition.isExternallyManagedInitMethod(methodName)) {
beanDefinition.registerExternallyManagedInitMethod(methodName);
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 methodName = calculateMethodIdentifierInHierarchy(it.next().getMethod());
if (!beanDefinition.isExternallyManagedDestroyMethod(methodName)) {
beanDefinition.registerExternallyManagedDestroyMethod(methodName);
String methodIdentifier = it.next().getIdentifier();
if (!beanDefinition.isExternallyManagedDestroyMethod(methodIdentifier)) {
beanDefinition.registerExternallyManagedDestroyMethod(methodIdentifier);
}
else {
it.remove();
@@ -177,15 +177,6 @@ public class InitDestroyAnnotationBeanPostProcessor
}
private String calculateMethodIdentifierInHierarchy(Method method) {
if (Modifier.isPrivate(method.getModifiers())) {
return method.getDeclaringClass() + "." + method.getName();
}
else {
return method.getName();
}
}
private LifecycleMetadata findLifecycleMetadata(Class clazz) {
if (this.lifecycleMetadataCache == null) {
// Happens after deserialization, during destruction...
@@ -238,15 +229,18 @@ public class InitDestroyAnnotationBeanPostProcessor
*/
private class LifecycleMetadata {
private final Set<LifecycleElement> initMethods = new LinkedHashSet<LifecycleElement>();
private final LinkedList<LifecycleElement> initMethods = new LinkedList<LifecycleElement>();
private final Set<LifecycleElement> destroyMethods = new LinkedHashSet<LifecycleElement>();
private final LinkedList<LifecycleElement> destroyMethods = new LinkedList<LifecycleElement>();
public void addInitMethod(Method method) {
this.initMethods.add(new LifecycleElement(method));
LifecycleElement element = new LifecycleElement(method);
if (!this.initMethods.contains(element)) {
this.initMethods.addFirst(element);
}
}
public Set<LifecycleElement> getInitMethods() {
public Collection<LifecycleElement> getInitMethods() {
return this.initMethods;
}
@@ -263,10 +257,13 @@ public class InitDestroyAnnotationBeanPostProcessor
}
public void addDestroyMethod(Method method) {
this.destroyMethods.add(new LifecycleElement(method));
LifecycleElement element = new LifecycleElement(method);
if (!this.destroyMethods.contains(element)) {
this.destroyMethods.addLast(element);
}
}
public Set<LifecycleElement> getDestroyMethods() {
public Collection<LifecycleElement> getDestroyMethods() {
return this.destroyMethods;
}
@@ -291,17 +288,25 @@ public class InitDestroyAnnotationBeanPostProcessor
private final Method method;
private final String identifier;
public LifecycleElement(Method method) {
if (method.getParameterTypes().length != 0) {
throw new IllegalStateException("Lifecycle method annotation requires a no-arg method: " + method);
}
this.method = method;
this.identifier = (Modifier.isPrivate(method.getModifiers()) ?
method.getDeclaringClass() + "." + method.getName() : method.getName());
}
public Method getMethod() {
return this.method;
}
public String getIdentifier() {
return this.identifier;
}
public void invoke(Object target) throws Throwable {
ReflectionUtils.makeAccessible(this.method);
this.method.invoke(target, (Object[]) null);
@@ -316,13 +321,12 @@ public class InitDestroyAnnotationBeanPostProcessor
return false;
}
LifecycleElement otherElement = (LifecycleElement) other;
return (this.method.getName().equals(otherElement.method.getName()) &&
this.method.getDeclaringClass().equals(otherElement.method.getDeclaringClass()));
return (this.identifier.equals(otherElement.identifier));
}
@Override
public int hashCode() {
return this.method.getName().hashCode();
return this.identifier.hashCode();
}
}