From 11d987009a982852a5ae4e7489cc9025c011519d Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Thu, 15 Oct 2009 10:33:05 +0000 Subject: [PATCH] revised destroy method lookup after deserialization (avoiding NPE in case of default-destroy-method; SPR-6211) --- .../support/DisposableBeanAdapter.java | 65 ++++++++++--------- 1 file changed, 36 insertions(+), 29 deletions(-) diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/DisposableBeanAdapter.java b/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/DisposableBeanAdapter.java index 540a83b3bb..fa0da8b6dc 100644 --- a/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/DisposableBeanAdapter.java +++ b/org.springframework.beans/src/main/java/org/springframework/beans/factory/support/DisposableBeanAdapter.java @@ -74,6 +74,7 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable { private final AccessControlContext acc; + /** * Create a new DisposableBeanAdapter for the given bean. * @param bean the bean instance (never null) @@ -97,27 +98,7 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable { if (destroyMethodName != null && !(this.invokeDisposableBean && "destroy".equals(destroyMethodName)) && !beanDefinition.isExternallyManagedDestroyMethod(destroyMethodName)) { this.destroyMethodName = destroyMethodName; - try { - if (System.getSecurityManager() != null) { - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { - destroyMethod = (nonPublicAccessAllowed ? - BeanUtils.findMethodWithMinimalParameters(bean.getClass(), destroyMethodName) : - BeanUtils.findMethodWithMinimalParameters(bean.getClass().getMethods(), destroyMethodName)); - return null; - } - }); - } - else { - this.destroyMethod = (this.nonPublicAccessAllowed ? - BeanUtils.findMethodWithMinimalParameters(bean.getClass(), destroyMethodName) : - BeanUtils.findMethodWithMinimalParameters(bean.getClass().getMethods(), destroyMethodName)); - } - } - catch (IllegalArgumentException ex) { - throw new BeanDefinitionValidationException("Couldn't find a unique destroy method on bean with name '" + - this.beanName + ": " + ex.getMessage()); - } + this.destroyMethod = determineDestroyMethod(); if (this.destroyMethod == null) { if (beanDefinition.isEnforceDestroyMethod()) { throw new BeanDefinitionValidationException("Couldn't find a destroy method named '" + @@ -193,7 +174,6 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable { try { if (System.getSecurityManager() != null) { AccessController.doPrivileged(new PrivilegedExceptionAction() { - public Object run() throws Exception { ((DisposableBean) bean).destroy(); return null; @@ -219,13 +199,39 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable { invokeCustomDestroyMethod(this.destroyMethod); } else if (this.destroyMethodName != null) { - this.destroyMethod = (this.nonPublicAccessAllowed ? - BeanUtils.findMethodWithMinimalParameters(this.bean.getClass(), this.destroyMethodName) : - BeanUtils.findMethodWithMinimalParameters(this.bean.getClass().getMethods(), this.destroyMethodName)); - invokeCustomDestroyMethod(this.destroyMethod); + Method methodToCall = determineDestroyMethod(); + if (methodToCall != null) { + invokeCustomDestroyMethod(methodToCall); + } } } + + private Method determineDestroyMethod() { + try { + if (System.getSecurityManager() != null) { + return AccessController.doPrivileged(new PrivilegedAction() { + public Method run() { + return findDestroyMethod(); + } + }); + } + else { + return findDestroyMethod(); + } + } + catch (IllegalArgumentException ex) { + throw new BeanDefinitionValidationException("Couldn't find a unique destroy method on bean with name '" + + this.beanName + ": " + ex.getMessage()); + } + } + + private Method findDestroyMethod() { + return (this.nonPublicAccessAllowed ? + BeanUtils.findMethodWithMinimalParameters(this.bean.getClass(), this.destroyMethodName) : + BeanUtils.findMethodWithMinimalParameters(this.bean.getClass().getMethods(), this.destroyMethodName)); + } + /** * Invoke the specified custom destroy method on the given bean. *

This implementation invokes a no-arg method if found, else checking @@ -250,7 +256,6 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable { return null; } }); - try { AccessController.doPrivileged(new PrivilegedExceptionAction() { public Object run() throws Exception { @@ -258,7 +263,8 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable { return null; } }, acc); - } catch (PrivilegedActionException pax) { + } + catch (PrivilegedActionException pax) { throw (InvocationTargetException) pax.getException(); } } @@ -266,7 +272,8 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable { ReflectionUtils.makeAccessible(destroyMethod); destroyMethod.invoke(bean, args); } - } catch (InvocationTargetException ex) { + } + catch (InvocationTargetException ex) { String msg = "Invocation of destroy method '" + this.destroyMethodName + "' failed on bean with name '" + this.beanName + "'"; if (logger.isDebugEnabled()) {