From d6345db7c9886e5675a45f8b2612cd780ead23d9 Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Tue, 19 Jul 2022 21:00:55 +0200 Subject: [PATCH] Use target of the FactoryBean only if the FactoryBean is public This commit polishes 85d4a79 so that the target type of factory bean is only considered if the FactoryBean is accessible. If the FactoryBean requires protected access, we still generate the code in the package of the FactoryBean. Those two commits combined are actually providing a fix for the use case described in gh-28809. Closes gh-28809 --- .../DefaultBeanRegistrationCodeFragments.java | 5 ++- ...ultBeanRegistrationCodeFragmentsTests.java | 17 +++++---- .../beans/factory/aot/TestBean.java | 25 ++++++++++++ .../factory/aot/TestBeanFactoryBean.java | 38 +++++++++++++++++++ 4 files changed, 76 insertions(+), 9 deletions(-) create mode 100644 spring-beans/src/testFixtures/java/org/springframework/beans/factory/aot/TestBean.java create mode 100644 spring-beans/src/testFixtures/java/org/springframework/beans/factory/aot/TestBeanFactoryBean.java diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/aot/DefaultBeanRegistrationCodeFragments.java b/spring-beans/src/main/java/org/springframework/beans/factory/aot/DefaultBeanRegistrationCodeFragments.java index 97a3df3fd66..350289ea247 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/aot/DefaultBeanRegistrationCodeFragments.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/aot/DefaultBeanRegistrationCodeFragments.java @@ -21,6 +21,7 @@ import java.lang.reflect.Executable; import java.util.List; import java.util.function.Predicate; +import org.springframework.aot.generate.AccessVisibility; import org.springframework.aot.generate.GenerationContext; import org.springframework.aot.generate.MethodReference; import org.springframework.beans.factory.FactoryBean; @@ -80,7 +81,9 @@ class DefaultBeanRegistrationCodeFragments extends BeanRegistrationCodeFragments private Class extractDeclaringClass(Executable executable) { Class declaringClass = ClassUtils.getUserClass(executable.getDeclaringClass()); - if (executable instanceof Constructor && FactoryBean.class.isAssignableFrom(declaringClass)) { + if (executable instanceof Constructor + && AccessVisibility.forMember(executable) == AccessVisibility.PUBLIC + && FactoryBean.class.isAssignableFrom(declaringClass)) { return ResolvableType.forType(declaringClass).as(FactoryBean.class).getGeneric(0).toClass(); } return executable.getDeclaringClass(); diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/aot/DefaultBeanRegistrationCodeFragmentsTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/aot/DefaultBeanRegistrationCodeFragmentsTests.java index 6ac4dfef376..9f89171d494 100644 --- a/spring-beans/src/test/java/org/springframework/beans/factory/aot/DefaultBeanRegistrationCodeFragmentsTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/factory/aot/DefaultBeanRegistrationCodeFragmentsTests.java @@ -51,12 +51,19 @@ class DefaultBeanRegistrationCodeFragmentsTests { } @Test - void getTargetOnConstructorToFactoryBean() { + void getTargetOnConstructorToPublicFactoryBean() { RegisteredBean registeredBean = registerTestBean(TestBean.class); assertThat(createInstance(registeredBean).getTarget(registeredBean, TestBeanFactoryBean.class.getDeclaredConstructors()[0])).isEqualTo(TestBean.class); } + @Test + void getTargetOnConstructorToProtectedFactoryBean() { + RegisteredBean registeredBean = registerTestBean(TestBean.class); + assertThat(createInstance(registeredBean).getTarget(registeredBean, + PrivilegedTestBeanFactoryBean.class.getDeclaredConstructors()[0])).isEqualTo(PrivilegedTestBeanFactoryBean.class); + } + @Test void getTargetOnMethod() { RegisteredBean registeredBean = registerTestBean(TestBean.class); @@ -135,13 +142,7 @@ class DefaultBeanRegistrationCodeFragmentsTests { return "Test"; } - @SuppressWarnings("unused") - static class TestBean { - - } - - - static class TestBeanFactoryBean implements FactoryBean { + static class PrivilegedTestBeanFactoryBean implements FactoryBean { @Override public TestBean getObject() throws Exception { diff --git a/spring-beans/src/testFixtures/java/org/springframework/beans/factory/aot/TestBean.java b/spring-beans/src/testFixtures/java/org/springframework/beans/factory/aot/TestBean.java new file mode 100644 index 00000000000..f52c20a90f9 --- /dev/null +++ b/spring-beans/src/testFixtures/java/org/springframework/beans/factory/aot/TestBean.java @@ -0,0 +1,25 @@ +/* + * Copyright 2002-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.beans.factory.aot; + +/** + * An empty test bean used by code generation. + * + * @author Stephane Nicoll + */ +public class TestBean { +} diff --git a/spring-beans/src/testFixtures/java/org/springframework/beans/factory/aot/TestBeanFactoryBean.java b/spring-beans/src/testFixtures/java/org/springframework/beans/factory/aot/TestBeanFactoryBean.java new file mode 100644 index 00000000000..a87d8670cf5 --- /dev/null +++ b/spring-beans/src/testFixtures/java/org/springframework/beans/factory/aot/TestBeanFactoryBean.java @@ -0,0 +1,38 @@ +/* + * Copyright 2002-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.beans.factory.aot; + +import org.springframework.beans.factory.FactoryBean; + +/** + * A public {@link FactoryBean}. + * + * @author Stephane Nicoll + */ +public class TestBeanFactoryBean implements FactoryBean { + + @Override + public TestBean getObject() throws Exception { + return new TestBean(); + } + + @Override + public Class getObjectType() { + return TestBean.class; + } + +}