Merge branch '5.3.x'
# Conflicts: # spring-beans/src/main/java/org/springframework/beans/factory/support/DisposableBeanAdapter.java
This commit is contained in:
commit
e314a79fb0
|
|
@ -56,6 +56,8 @@ import org.springframework.util.StringUtils;
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||||
|
|
||||||
|
private static final String DESTROY_METHOD_NAME = "destroy";
|
||||||
|
|
||||||
private static final String CLOSE_METHOD_NAME = "close";
|
private static final String CLOSE_METHOD_NAME = "close";
|
||||||
|
|
||||||
private static final String SHUTDOWN_METHOD_NAME = "shutdown";
|
private static final String SHUTDOWN_METHOD_NAME = "shutdown";
|
||||||
|
|
@ -67,9 +69,11 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||||
|
|
||||||
private final String beanName;
|
private final String beanName;
|
||||||
|
|
||||||
|
private final boolean nonPublicAccessAllowed;
|
||||||
|
|
||||||
private final boolean invokeDisposableBean;
|
private final boolean invokeDisposableBean;
|
||||||
|
|
||||||
private final boolean nonPublicAccessAllowed;
|
private boolean invokeAutoCloseable;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private String destroyMethodName;
|
private String destroyMethodName;
|
||||||
|
|
@ -95,36 +99,43 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||||
Assert.notNull(bean, "Disposable bean must not be null");
|
Assert.notNull(bean, "Disposable bean must not be null");
|
||||||
this.bean = bean;
|
this.bean = bean;
|
||||||
this.beanName = beanName;
|
this.beanName = beanName;
|
||||||
this.invokeDisposableBean =
|
|
||||||
(this.bean instanceof DisposableBean && !beanDefinition.isExternallyManagedDestroyMethod("destroy"));
|
|
||||||
this.nonPublicAccessAllowed = beanDefinition.isNonPublicAccessAllowed();
|
this.nonPublicAccessAllowed = beanDefinition.isNonPublicAccessAllowed();
|
||||||
|
this.invokeDisposableBean = (bean instanceof DisposableBean &&
|
||||||
|
!beanDefinition.isExternallyManagedDestroyMethod(DESTROY_METHOD_NAME));
|
||||||
|
|
||||||
String destroyMethodName = inferDestroyMethodIfNecessary(bean, beanDefinition);
|
String destroyMethodName = inferDestroyMethodIfNecessary(bean, beanDefinition);
|
||||||
if (destroyMethodName != null && !(this.invokeDisposableBean && "destroy".equals(destroyMethodName)) &&
|
if (destroyMethodName != null &&
|
||||||
|
!(this.invokeDisposableBean && DESTROY_METHOD_NAME.equals(destroyMethodName)) &&
|
||||||
!beanDefinition.isExternallyManagedDestroyMethod(destroyMethodName)) {
|
!beanDefinition.isExternallyManagedDestroyMethod(destroyMethodName)) {
|
||||||
this.destroyMethodName = destroyMethodName;
|
|
||||||
Method destroyMethod = determineDestroyMethod(destroyMethodName);
|
this.invokeAutoCloseable = (bean instanceof AutoCloseable && CLOSE_METHOD_NAME.equals(destroyMethodName));
|
||||||
if (destroyMethod == null) {
|
if (!this.invokeAutoCloseable) {
|
||||||
if (beanDefinition.isEnforceDestroyMethod()) {
|
this.destroyMethodName = destroyMethodName;
|
||||||
throw new BeanDefinitionValidationException("Could not find a destroy method named '" +
|
Method destroyMethod = determineDestroyMethod(destroyMethodName);
|
||||||
destroyMethodName + "' on bean with name '" + beanName + "'");
|
if (destroyMethod == null) {
|
||||||
}
|
if (beanDefinition.isEnforceDestroyMethod()) {
|
||||||
}
|
throw new BeanDefinitionValidationException("Could not find a destroy method named '" +
|
||||||
else {
|
destroyMethodName + "' on bean with name '" + beanName + "'");
|
||||||
if (destroyMethod.getParameterCount() > 0) {
|
|
||||||
Class<?>[] paramTypes = destroyMethod.getParameterTypes();
|
|
||||||
if (paramTypes.length > 1) {
|
|
||||||
throw new BeanDefinitionValidationException("Method '" + destroyMethodName + "' of bean '" +
|
|
||||||
beanName + "' has more than one parameter - not supported as destroy method");
|
|
||||||
}
|
|
||||||
else if (paramTypes.length == 1 && boolean.class != paramTypes[0]) {
|
|
||||||
throw new BeanDefinitionValidationException("Method '" + destroyMethodName + "' of bean '" +
|
|
||||||
beanName + "' has a non-boolean parameter - not supported as destroy method");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
destroyMethod = ClassUtils.getInterfaceMethodIfPossible(destroyMethod);
|
else {
|
||||||
|
if (destroyMethod.getParameterCount() > 0) {
|
||||||
|
Class<?>[] paramTypes = destroyMethod.getParameterTypes();
|
||||||
|
if (paramTypes.length > 1) {
|
||||||
|
throw new BeanDefinitionValidationException("Method '" + destroyMethodName + "' of bean '" +
|
||||||
|
beanName + "' has more than one parameter - not supported as destroy method");
|
||||||
|
}
|
||||||
|
else if (paramTypes.length == 1 && boolean.class != paramTypes[0]) {
|
||||||
|
throw new BeanDefinitionValidationException("Method '" + destroyMethodName + "' of bean '" +
|
||||||
|
beanName + "' has a non-boolean parameter - not supported as destroy method");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
destroyMethod = ClassUtils.getInterfaceMethodIfPossible(destroyMethod);
|
||||||
|
}
|
||||||
|
this.destroyMethod = destroyMethod;
|
||||||
}
|
}
|
||||||
this.destroyMethod = destroyMethod;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.beanPostProcessors = filterPostProcessors(postProcessors, bean);
|
this.beanPostProcessors = filterPostProcessors(postProcessors, bean);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -138,22 +149,23 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||||
Assert.notNull(bean, "Disposable bean must not be null");
|
Assert.notNull(bean, "Disposable bean must not be null");
|
||||||
this.bean = bean;
|
this.bean = bean;
|
||||||
this.beanName = bean.getClass().getName();
|
this.beanName = bean.getClass().getName();
|
||||||
this.invokeDisposableBean = (this.bean instanceof DisposableBean);
|
|
||||||
this.nonPublicAccessAllowed = true;
|
this.nonPublicAccessAllowed = true;
|
||||||
|
this.invokeDisposableBean = (this.bean instanceof DisposableBean);
|
||||||
this.beanPostProcessors = filterPostProcessors(postProcessors, bean);
|
this.beanPostProcessors = filterPostProcessors(postProcessors, bean);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new DisposableBeanAdapter for the given bean.
|
* Create a new DisposableBeanAdapter for the given bean.
|
||||||
*/
|
*/
|
||||||
private DisposableBeanAdapter(Object bean, String beanName, boolean invokeDisposableBean,
|
private DisposableBeanAdapter(Object bean, String beanName, boolean nonPublicAccessAllowed,
|
||||||
boolean nonPublicAccessAllowed, @Nullable String destroyMethodName,
|
boolean invokeDisposableBean, boolean invokeAutoCloseable, @Nullable String destroyMethodName,
|
||||||
@Nullable List<DestructionAwareBeanPostProcessor> postProcessors) {
|
@Nullable List<DestructionAwareBeanPostProcessor> postProcessors) {
|
||||||
|
|
||||||
this.bean = bean;
|
this.bean = bean;
|
||||||
this.beanName = beanName;
|
this.beanName = beanName;
|
||||||
this.invokeDisposableBean = invokeDisposableBean;
|
|
||||||
this.nonPublicAccessAllowed = nonPublicAccessAllowed;
|
this.nonPublicAccessAllowed = nonPublicAccessAllowed;
|
||||||
|
this.invokeDisposableBean = invokeDisposableBean;
|
||||||
|
this.invokeAutoCloseable = invokeAutoCloseable;
|
||||||
this.destroyMethodName = destroyMethodName;
|
this.destroyMethodName = destroyMethodName;
|
||||||
this.beanPostProcessors = postProcessors;
|
this.beanPostProcessors = postProcessors;
|
||||||
}
|
}
|
||||||
|
|
@ -190,7 +202,24 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.destroyMethod != null) {
|
if (this.invokeAutoCloseable) {
|
||||||
|
if (logger.isTraceEnabled()) {
|
||||||
|
logger.trace("Invoking close() on bean with name '" + this.beanName + "'");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
((AutoCloseable) this.bean).close();
|
||||||
|
}
|
||||||
|
catch (Throwable ex) {
|
||||||
|
String msg = "Invocation of close method failed on bean with name '" + this.beanName + "'";
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.warn(msg, ex);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
logger.warn(msg + ": " + ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (this.destroyMethod != null) {
|
||||||
invokeCustomDestroyMethod(this.destroyMethod);
|
invokeCustomDestroyMethod(this.destroyMethod);
|
||||||
}
|
}
|
||||||
else if (this.destroyMethodName != null) {
|
else if (this.destroyMethodName != null) {
|
||||||
|
|
@ -233,7 +262,7 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||||
args[0] = Boolean.TRUE;
|
args[0] = Boolean.TRUE;
|
||||||
}
|
}
|
||||||
if (logger.isTraceEnabled()) {
|
if (logger.isTraceEnabled()) {
|
||||||
logger.trace("Invoking destroy method '" + this.destroyMethodName +
|
logger.trace("Invoking custom destroy method '" + this.destroyMethodName +
|
||||||
"' on bean with name '" + this.beanName + "'");
|
"' on bean with name '" + this.beanName + "'");
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|
@ -241,7 +270,7 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||||
destroyMethod.invoke(this.bean, args);
|
destroyMethod.invoke(this.bean, args);
|
||||||
}
|
}
|
||||||
catch (InvocationTargetException ex) {
|
catch (InvocationTargetException ex) {
|
||||||
String msg = "Destroy method '" + this.destroyMethodName + "' on bean with name '" +
|
String msg = "Custom destroy method '" + this.destroyMethodName + "' on bean with name '" +
|
||||||
this.beanName + "' threw an exception";
|
this.beanName + "' threw an exception";
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.warn(msg, ex.getTargetException());
|
logger.warn(msg, ex.getTargetException());
|
||||||
|
|
@ -251,7 +280,7 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Throwable ex) {
|
catch (Throwable ex) {
|
||||||
logger.warn("Failed to invoke destroy method '" + this.destroyMethodName +
|
logger.warn("Failed to invoke custom destroy method '" + this.destroyMethodName +
|
||||||
"' on bean with name '" + this.beanName + "'", ex);
|
"' on bean with name '" + this.beanName + "'", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -271,8 +300,9 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new DisposableBeanAdapter(this.bean, this.beanName, this.invokeDisposableBean,
|
return new DisposableBeanAdapter(
|
||||||
this.nonPublicAccessAllowed, this.destroyMethodName, serializablePostProcessors);
|
this.bean, this.beanName, this.nonPublicAccessAllowed, this.invokeDisposableBean,
|
||||||
|
this.invokeAutoCloseable, this.destroyMethodName, serializablePostProcessors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -282,10 +312,7 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||||
* @param beanDefinition the corresponding bean definition
|
* @param beanDefinition the corresponding bean definition
|
||||||
*/
|
*/
|
||||||
public static boolean hasDestroyMethod(Object bean, RootBeanDefinition beanDefinition) {
|
public static boolean hasDestroyMethod(Object bean, RootBeanDefinition beanDefinition) {
|
||||||
if (bean instanceof DisposableBean || bean instanceof AutoCloseable) {
|
return (bean instanceof DisposableBean || inferDestroyMethodIfNecessary(bean, beanDefinition) != null);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return inferDestroyMethodIfNecessary(bean, beanDefinition) != null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -307,21 +334,27 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||||
String destroyMethodName = beanDefinition.resolvedDestroyMethodName;
|
String destroyMethodName = beanDefinition.resolvedDestroyMethodName;
|
||||||
if (destroyMethodName == null) {
|
if (destroyMethodName == null) {
|
||||||
destroyMethodName = beanDefinition.getDestroyMethodName();
|
destroyMethodName = beanDefinition.getDestroyMethodName();
|
||||||
|
boolean autoCloseable = (bean instanceof AutoCloseable);
|
||||||
if (AbstractBeanDefinition.INFER_METHOD.equals(destroyMethodName) ||
|
if (AbstractBeanDefinition.INFER_METHOD.equals(destroyMethodName) ||
|
||||||
(destroyMethodName == null && bean instanceof AutoCloseable)) {
|
(destroyMethodName == null && autoCloseable)) {
|
||||||
// Only perform destroy method inference or Closeable detection
|
// Only perform destroy method inference in case of the bean
|
||||||
// in case of the bean not explicitly implementing DisposableBean
|
// not explicitly implementing the DisposableBean interface
|
||||||
destroyMethodName = null;
|
destroyMethodName = null;
|
||||||
if (!(bean instanceof DisposableBean)) {
|
if (!(bean instanceof DisposableBean)) {
|
||||||
try {
|
if (autoCloseable) {
|
||||||
destroyMethodName = bean.getClass().getMethod(CLOSE_METHOD_NAME).getName();
|
destroyMethodName = CLOSE_METHOD_NAME;
|
||||||
}
|
}
|
||||||
catch (NoSuchMethodException ex) {
|
else {
|
||||||
try {
|
try {
|
||||||
destroyMethodName = bean.getClass().getMethod(SHUTDOWN_METHOD_NAME).getName();
|
destroyMethodName = bean.getClass().getMethod(CLOSE_METHOD_NAME).getName();
|
||||||
}
|
}
|
||||||
catch (NoSuchMethodException ex2) {
|
catch (NoSuchMethodException ex) {
|
||||||
// no candidate destroy method found
|
try {
|
||||||
|
destroyMethodName = bean.getClass().getMethod(SHUTDOWN_METHOD_NAME).getName();
|
||||||
|
}
|
||||||
|
catch (NoSuchMethodException ex2) {
|
||||||
|
// no candidate destroy method found
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2019 the original author or authors.
|
* Copyright 2002-2021 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -26,7 +26,6 @@ import org.springframework.context.support.GenericXmlApplicationContext;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Chris Beams
|
* @author Chris Beams
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
|
|
@ -47,6 +46,7 @@ public class DestroyMethodInferenceTests {
|
||||||
WithLocalShutdownMethod c7 = ctx.getBean("c7", WithLocalShutdownMethod.class);
|
WithLocalShutdownMethod c7 = ctx.getBean("c7", WithLocalShutdownMethod.class);
|
||||||
WithInheritedCloseMethod c8 = ctx.getBean("c8", WithInheritedCloseMethod.class);
|
WithInheritedCloseMethod c8 = ctx.getBean("c8", WithInheritedCloseMethod.class);
|
||||||
WithDisposableBean c9 = ctx.getBean("c9", WithDisposableBean.class);
|
WithDisposableBean c9 = ctx.getBean("c9", WithDisposableBean.class);
|
||||||
|
WithAutoCloseable c10 = ctx.getBean("c10", WithAutoCloseable.class);
|
||||||
|
|
||||||
assertThat(c0.closed).as("c0").isFalse();
|
assertThat(c0.closed).as("c0").isFalse();
|
||||||
assertThat(c1.closed).as("c1").isFalse();
|
assertThat(c1.closed).as("c1").isFalse();
|
||||||
|
|
@ -58,6 +58,8 @@ public class DestroyMethodInferenceTests {
|
||||||
assertThat(c7.closed).as("c7").isFalse();
|
assertThat(c7.closed).as("c7").isFalse();
|
||||||
assertThat(c8.closed).as("c8").isFalse();
|
assertThat(c8.closed).as("c8").isFalse();
|
||||||
assertThat(c9.closed).as("c9").isFalse();
|
assertThat(c9.closed).as("c9").isFalse();
|
||||||
|
assertThat(c10.closed).as("c10").isFalse();
|
||||||
|
|
||||||
ctx.close();
|
ctx.close();
|
||||||
assertThat(c0.closed).as("c0").isTrue();
|
assertThat(c0.closed).as("c0").isTrue();
|
||||||
assertThat(c1.closed).as("c1").isTrue();
|
assertThat(c1.closed).as("c1").isTrue();
|
||||||
|
|
@ -69,6 +71,7 @@ public class DestroyMethodInferenceTests {
|
||||||
assertThat(c7.closed).as("c7").isTrue();
|
assertThat(c7.closed).as("c7").isTrue();
|
||||||
assertThat(c8.closed).as("c8").isFalse();
|
assertThat(c8.closed).as("c8").isFalse();
|
||||||
assertThat(c9.closed).as("c9").isTrue();
|
assertThat(c9.closed).as("c9").isTrue();
|
||||||
|
assertThat(c10.closed).as("c10").isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -80,21 +83,29 @@ public class DestroyMethodInferenceTests {
|
||||||
WithLocalCloseMethod x3 = ctx.getBean("x3", WithLocalCloseMethod.class);
|
WithLocalCloseMethod x3 = ctx.getBean("x3", WithLocalCloseMethod.class);
|
||||||
WithNoCloseMethod x4 = ctx.getBean("x4", WithNoCloseMethod.class);
|
WithNoCloseMethod x4 = ctx.getBean("x4", WithNoCloseMethod.class);
|
||||||
WithInheritedCloseMethod x8 = ctx.getBean("x8", WithInheritedCloseMethod.class);
|
WithInheritedCloseMethod x8 = ctx.getBean("x8", WithInheritedCloseMethod.class);
|
||||||
|
WithDisposableBean x9 = ctx.getBean("x9", WithDisposableBean.class);
|
||||||
|
WithAutoCloseable x10 = ctx.getBean("x10", WithAutoCloseable.class);
|
||||||
|
|
||||||
assertThat(x1.closed).isFalse();
|
assertThat(x1.closed).isFalse();
|
||||||
assertThat(x2.closed).isFalse();
|
assertThat(x2.closed).isFalse();
|
||||||
assertThat(x3.closed).isFalse();
|
assertThat(x3.closed).isFalse();
|
||||||
assertThat(x4.closed).isFalse();
|
assertThat(x4.closed).isFalse();
|
||||||
|
assertThat(x8.closed).isFalse();
|
||||||
|
assertThat(x9.closed).isFalse();
|
||||||
|
assertThat(x10.closed).isFalse();
|
||||||
|
|
||||||
ctx.close();
|
ctx.close();
|
||||||
assertThat(x1.closed).isFalse();
|
assertThat(x1.closed).isFalse();
|
||||||
assertThat(x2.closed).isTrue();
|
assertThat(x2.closed).isTrue();
|
||||||
assertThat(x3.closed).isTrue();
|
assertThat(x3.closed).isTrue();
|
||||||
assertThat(x4.closed).isFalse();
|
assertThat(x4.closed).isFalse();
|
||||||
assertThat(x8.closed).isFalse();
|
assertThat(x8.closed).isFalse();
|
||||||
|
assertThat(x9.closed).isTrue();
|
||||||
|
assertThat(x10.closed).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Configuration
|
@Configuration(proxyBeanMethods = false)
|
||||||
static class Config {
|
static class Config {
|
||||||
|
|
||||||
@Bean(destroyMethod = "explicitClose")
|
@Bean(destroyMethod = "explicitClose")
|
||||||
|
|
@ -155,6 +166,11 @@ public class DestroyMethodInferenceTests {
|
||||||
public WithDisposableBean c9() {
|
public WithDisposableBean c9() {
|
||||||
return new WithDisposableBean();
|
return new WithDisposableBean();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public WithAutoCloseable c10() {
|
||||||
|
return new WithAutoCloseable();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -189,17 +205,6 @@ public class DestroyMethodInferenceTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static class WithDisposableBean implements DisposableBean {
|
|
||||||
|
|
||||||
boolean closed = false;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void destroy() {
|
|
||||||
closed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static class WithNoCloseMethod {
|
static class WithNoCloseMethod {
|
||||||
|
|
||||||
boolean closed = false;
|
boolean closed = false;
|
||||||
|
|
@ -215,4 +220,26 @@ public class DestroyMethodInferenceTests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static class WithDisposableBean implements DisposableBean {
|
||||||
|
|
||||||
|
boolean closed = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy() {
|
||||||
|
closed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static class WithAutoCloseable implements AutoCloseable {
|
||||||
|
|
||||||
|
boolean closed = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
closed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,10 +15,16 @@
|
||||||
class="org.springframework.context.annotation.DestroyMethodInferenceTests.WithInheritedCloseMethod"
|
class="org.springframework.context.annotation.DestroyMethodInferenceTests.WithInheritedCloseMethod"
|
||||||
destroy-method=""/>
|
destroy-method=""/>
|
||||||
|
|
||||||
|
<bean id="x9"
|
||||||
|
class="org.springframework.context.annotation.DestroyMethodInferenceTests.WithDisposableBean"
|
||||||
|
destroy-method=""/>
|
||||||
|
|
||||||
|
<bean id="x10"
|
||||||
|
class="org.springframework.context.annotation.DestroyMethodInferenceTests.WithAutoCloseable"/>
|
||||||
|
|
||||||
<beans default-destroy-method="(inferred)">
|
<beans default-destroy-method="(inferred)">
|
||||||
<bean id="x3"
|
<bean id="x3"
|
||||||
class="org.springframework.context.annotation.DestroyMethodInferenceTests$WithLocalCloseMethod"/>
|
class="org.springframework.context.annotation.DestroyMethodInferenceTests$WithLocalCloseMethod"/>
|
||||||
|
|
||||||
<bean id="x4"
|
<bean id="x4"
|
||||||
class="org.springframework.context.annotation.DestroyMethodInferenceTests$WithNoCloseMethod"/>
|
class="org.springframework.context.annotation.DestroyMethodInferenceTests$WithNoCloseMethod"/>
|
||||||
</beans>
|
</beans>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue