Skip to content

Commit 520a113

Browse files
committed
Polishing (aligned with 6.1.x)
1 parent ceeb552 commit 520a113

File tree

8 files changed

+112
-96
lines changed

8 files changed

+112
-96
lines changed

Diff for: spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2023 the original author or authors.
2+
* Copyright 2002-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -835,11 +835,11 @@ protected Class<?> getTypeForFactoryMethod(String beanName, RootBeanDefinition m
835835
/**
836836
* This implementation attempts to query the FactoryBean's generic parameter metadata
837837
* if present to determine the object type. If not present, i.e. the FactoryBean is
838-
* declared as a raw type, checks the FactoryBean's {@code getObjectType} method
838+
* declared as a raw type, it checks the FactoryBean's {@code getObjectType} method
839839
* on a plain instance of the FactoryBean, without bean properties applied yet.
840-
* If this doesn't return a type yet, and {@code allowInit} is {@code true} a
841-
* full creation of the FactoryBean is used as fallback (through delegation to the
842-
* superclass's implementation).
840+
* If this doesn't return a type yet and {@code allowInit} is {@code true}, full
841+
* creation of the FactoryBean is attempted as fallback (through delegation to the
842+
* superclass implementation).
843843
* <p>The shortcut check for a FactoryBean is only applied in case of a singleton
844844
* FactoryBean. If the FactoryBean instance itself is not kept as singleton,
845845
* it will be fully created to check the type of its exposed object.

Diff for: spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1695,7 +1695,7 @@ protected boolean isFactoryBean(String beanName, RootBeanDefinition mbd) {
16951695
* already. The implementation is allowed to instantiate the target factory bean if
16961696
* {@code allowInit} is {@code true} and the type cannot be determined another way;
16971697
* otherwise it is restricted to introspecting signatures and related metadata.
1698-
* <p>If no {@link FactoryBean#OBJECT_TYPE_ATTRIBUTE} if set on the bean definition
1698+
* <p>If no {@link FactoryBean#OBJECT_TYPE_ATTRIBUTE} is set on the bean definition
16991699
* and {@code allowInit} is {@code true}, the default implementation will create
17001700
* the FactoryBean via {@code getBean} to call its {@code getObjectType} method.
17011701
* Subclasses are encouraged to optimize this, typically by inspecting the generic

Diff for: spring-context/src/test/java/org/springframework/context/annotation/ConfigurationWithFactoryBeanBeanEarlyDeductionTests.java renamed to spring-context/src/test/java/org/springframework/context/annotation/ConfigurationWithFactoryBeanEarlyDeductionTests.java

+60-40
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2019 the original author or authors.
2+
* Copyright 2002-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -29,7 +29,9 @@
2929
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
3030
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
3131
import org.springframework.beans.factory.support.GenericBeanDefinition;
32+
import org.springframework.beans.factory.support.RootBeanDefinition;
3233
import org.springframework.context.support.GenericApplicationContext;
34+
import org.springframework.core.ResolvableType;
3335
import org.springframework.core.type.AnnotationMetadata;
3436

3537
import static org.assertj.core.api.Assertions.assertThat;
@@ -39,51 +41,62 @@
3941
* {@link FactoryBean FactoryBeans} defined in the configuration.
4042
*
4143
* @author Phillip Webb
44+
* @author Juergen Hoeller
4245
*/
43-
public class ConfigurationWithFactoryBeanBeanEarlyDeductionTests {
46+
class ConfigurationWithFactoryBeanEarlyDeductionTests {
4447

4548
@Test
46-
public void preFreezeDirect() {
49+
void preFreezeDirect() {
4750
assertPreFreeze(DirectConfiguration.class);
4851
}
4952

5053
@Test
51-
public void postFreezeDirect() {
54+
void postFreezeDirect() {
5255
assertPostFreeze(DirectConfiguration.class);
5356
}
5457

5558
@Test
56-
public void preFreezeGenericMethod() {
59+
void preFreezeGenericMethod() {
5760
assertPreFreeze(GenericMethodConfiguration.class);
5861
}
5962

6063
@Test
61-
public void postFreezeGenericMethod() {
64+
void postFreezeGenericMethod() {
6265
assertPostFreeze(GenericMethodConfiguration.class);
6366
}
6467

6568
@Test
66-
public void preFreezeGenericClass() {
69+
void preFreezeGenericClass() {
6770
assertPreFreeze(GenericClassConfiguration.class);
6871
}
6972

7073
@Test
71-
public void postFreezeGenericClass() {
74+
void postFreezeGenericClass() {
7275
assertPostFreeze(GenericClassConfiguration.class);
7376
}
7477

7578
@Test
76-
public void preFreezeAttribute() {
79+
void preFreezeAttribute() {
7780
assertPreFreeze(AttributeClassConfiguration.class);
7881
}
7982

8083
@Test
81-
public void postFreezeAttribute() {
84+
void postFreezeAttribute() {
8285
assertPostFreeze(AttributeClassConfiguration.class);
8386
}
8487

8588
@Test
86-
public void preFreezeUnresolvedGenericFactoryBean() {
89+
void preFreezeTargetType() {
90+
assertPreFreeze(TargetTypeConfiguration.class);
91+
}
92+
93+
@Test
94+
void postFreezeTargetType() {
95+
assertPostFreeze(TargetTypeConfiguration.class);
96+
}
97+
98+
@Test
99+
void preFreezeUnresolvedGenericFactoryBean() {
87100
// Covers the case where a @Configuration is picked up via component scanning
88101
// and its bean definition only has a String bean class. In such cases
89102
// beanDefinition.hasBeanClass() returns false so we need to actually
@@ -108,14 +121,13 @@ public void preFreezeUnresolvedGenericFactoryBean() {
108121
}
109122
}
110123

124+
111125
private void assertPostFreeze(Class<?> configurationClass) {
112-
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
113-
configurationClass);
126+
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(configurationClass);
114127
assertContainsMyBeanName(context);
115128
}
116129

117-
private void assertPreFreeze(Class<?> configurationClass,
118-
BeanFactoryPostProcessor... postProcessors) {
130+
private void assertPreFreeze(Class<?> configurationClass, BeanFactoryPostProcessor... postProcessors) {
119131
NameCollectingBeanFactoryPostProcessor postProcessor = new NameCollectingBeanFactoryPostProcessor();
120132
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
121133
try {
@@ -138,41 +150,38 @@ private void assertContainsMyBeanName(String[] names) {
138150
assertThat(names).containsExactly("myBean");
139151
}
140152

141-
private static class NameCollectingBeanFactoryPostProcessor
142-
implements BeanFactoryPostProcessor {
153+
154+
private static class NameCollectingBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
143155

144156
private String[] names;
145157

146158
@Override
147-
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
148-
throws BeansException {
149-
this.names = beanFactory.getBeanNamesForType(MyBean.class, true, false);
159+
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
160+
ResolvableType typeToMatch = ResolvableType.forClassWithGenerics(MyBean.class, String.class);
161+
this.names = beanFactory.getBeanNamesForType(typeToMatch, true, false);
150162
}
151163

152164
public String[] getNames() {
153165
return this.names;
154166
}
155-
156167
}
157168

158169
@Configuration
159170
static class DirectConfiguration {
160171

161172
@Bean
162-
MyBean myBean() {
163-
return new MyBean();
173+
MyBean<String> myBean() {
174+
return new MyBean<>();
164175
}
165-
166176
}
167177

168178
@Configuration
169179
static class GenericMethodConfiguration {
170180

171181
@Bean
172-
FactoryBean<MyBean> myBean() {
173-
return new TestFactoryBean<>(new MyBean());
182+
FactoryBean<MyBean<String>> myBean() {
183+
return new TestFactoryBean<>(new MyBean<>());
174184
}
175-
176185
}
177186

178187
@Configuration
@@ -182,13 +191,11 @@ static class GenericClassConfiguration {
182191
MyFactoryBean myBean() {
183192
return new MyFactoryBean();
184193
}
185-
186194
}
187195

188196
@Configuration
189197
@Import(AttributeClassRegistrar.class)
190198
static class AttributeClassConfiguration {
191-
192199
}
193200

194201
static class AttributeClassRegistrar implements ImportBeanDefinitionRegistrar {
@@ -197,16 +204,34 @@ static class AttributeClassRegistrar implements ImportBeanDefinitionRegistrar {
197204
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
198205
BeanDefinition definition = BeanDefinitionBuilder.genericBeanDefinition(
199206
RawWithAbstractObjectTypeFactoryBean.class).getBeanDefinition();
200-
definition.setAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE, MyBean.class);
207+
definition.setAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE,
208+
ResolvableType.forClassWithGenerics(MyBean.class, String.class));
201209
registry.registerBeanDefinition("myBean", definition);
202210
}
211+
}
203212

213+
@Configuration
214+
@Import(TargetTypeRegistrar.class)
215+
static class TargetTypeConfiguration {
216+
}
217+
218+
static class TargetTypeRegistrar implements ImportBeanDefinitionRegistrar {
219+
220+
@Override
221+
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
222+
RootBeanDefinition definition = new RootBeanDefinition(RawWithAbstractObjectTypeFactoryBean.class);
223+
definition.setTargetType(ResolvableType.forClassWithGenerics(FactoryBean.class,
224+
ResolvableType.forClassWithGenerics(MyBean.class, String.class)));
225+
definition.setAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE,
226+
ResolvableType.forClassWithGenerics(MyBean.class, String.class));
227+
registry.registerBeanDefinition("myBean", definition);
228+
}
204229
}
205230

206231
abstract static class AbstractMyBean {
207232
}
208233

209-
static class MyBean extends AbstractMyBean {
234+
static class MyBean<T> extends AbstractMyBean {
210235
}
211236

212237
static class TestFactoryBean<T> implements FactoryBean<T> {
@@ -218,39 +243,34 @@ public TestFactoryBean(T instance) {
218243
}
219244

220245
@Override
221-
public T getObject() throws Exception {
246+
public T getObject() {
222247
return this.instance;
223248
}
224249

225250
@Override
226251
public Class<?> getObjectType() {
227252
return this.instance.getClass();
228253
}
229-
230254
}
231255

232-
static class MyFactoryBean extends TestFactoryBean<MyBean> {
256+
static class MyFactoryBean extends TestFactoryBean<MyBean<String>> {
233257

234258
public MyFactoryBean() {
235-
super(new MyBean());
259+
super(new MyBean<>());
236260
}
237-
238261
}
239262

240263
static class RawWithAbstractObjectTypeFactoryBean implements FactoryBean<Object> {
241264

242-
private final Object object = new MyBean();
243-
244265
@Override
245266
public Object getObject() throws Exception {
246-
return object;
267+
throw new IllegalStateException();
247268
}
248269

249270
@Override
250271
public Class<?> getObjectType() {
251272
return MyBean.class;
252273
}
253-
254274
}
255275

256276
}

0 commit comments

Comments
 (0)