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:
parent
4375b9c89a
commit
3b9605bc57
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue