From ec3f59e6fea2b968ae00f41511c2e8ed6bda94d8 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Mon, 14 Nov 2022 23:37:05 +0100 Subject: [PATCH] Allow AutoCloseable dereferences on original AutoCloseable beans Closes gh-29480 --- .../beans/CachedIntrospectionResults.java | 16 +++++++++------- .../springframework/beans/BeanWrapperTests.java | 16 ++++++++++++++++ 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/spring-beans/src/main/java/org/springframework/beans/CachedIntrospectionResults.java b/spring-beans/src/main/java/org/springframework/beans/CachedIntrospectionResults.java index 73165cc0cb89..42e9acca27f1 100644 --- a/spring-beans/src/main/java/org/springframework/beans/CachedIntrospectionResults.java +++ b/spring-beans/src/main/java/org/springframework/beans/CachedIntrospectionResults.java @@ -295,7 +295,7 @@ private CachedIntrospectionResults(Class beanClass) throws BeansException { // Only allow URL attribute introspection, not content resolution continue; } - if (pd.getWriteMethod() == null && isInvalidReadOnlyPropertyType(pd.getPropertyType())) { + if (pd.getWriteMethod() == null && isInvalidReadOnlyPropertyType(pd.getPropertyType(), beanClass)) { // Ignore read-only properties such as ClassLoader - no need to bind to those continue; } @@ -345,7 +345,8 @@ private void introspectInterfaces(Class beanClass, Class currClass, Set 0 || method.getReturnType() == void.class || - isInvalidReadOnlyPropertyType(method.getReturnType())) { + isInvalidReadOnlyPropertyType(method.getReturnType(), method.getDeclaringClass())) { return false; } try { @@ -391,10 +392,11 @@ private boolean isPlainAccessor(Method method) { } } - private boolean isInvalidReadOnlyPropertyType(@Nullable Class returnType) { - return (returnType != null && (AutoCloseable.class.isAssignableFrom(returnType) || - ClassLoader.class.isAssignableFrom(returnType) || - ProtectionDomain.class.isAssignableFrom(returnType))); + private boolean isInvalidReadOnlyPropertyType(@Nullable Class returnType, Class beanClass) { + return (returnType != null && (ClassLoader.class.isAssignableFrom(returnType) || + ProtectionDomain.class.isAssignableFrom(returnType) || + (AutoCloseable.class.isAssignableFrom(returnType) && + !AutoCloseable.class.isAssignableFrom(beanClass)))); } diff --git a/spring-beans/src/test/java/org/springframework/beans/BeanWrapperTests.java b/spring-beans/src/test/java/org/springframework/beans/BeanWrapperTests.java index 30ab8b1716db..17a775a7f123 100644 --- a/spring-beans/src/test/java/org/springframework/beans/BeanWrapperTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/BeanWrapperTests.java @@ -216,6 +216,10 @@ void propertyDescriptors() throws Exception { assertThat(accessor.isReadableProperty("inputStream")).isFalse(); assertThat(accessor.isReadableProperty("filename")).isTrue(); assertThat(accessor.isReadableProperty("description")).isTrue(); + + accessor = createAccessor(new ActiveResource()); + + assertThat(accessor.isReadableProperty("resource")).isTrue(); } @Test @@ -376,6 +380,18 @@ public String getObject() { } + public static class ActiveResource implements AutoCloseable { + + public ActiveResource getResource() { + return this; + } + + @Override + public void close() throws Exception { + } + } + + public static class GetterWithOptional { public TestBean value;