Skip to content

Commit 94097fb

Browse files
committed
Polishing (aligned with 6.1.x)
1 parent e4ab2aa commit 94097fb

File tree

8 files changed

+110
-88
lines changed

8 files changed

+110
-88
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.
@@ -818,11 +818,11 @@ protected Class<?> getTypeForFactoryMethod(String beanName, RootBeanDefinition m
818818
/**
819819
* This implementation attempts to query the FactoryBean's generic parameter metadata
820820
* if present to determine the object type. If not present, i.e. the FactoryBean is
821-
* declared as a raw type, checks the FactoryBean's {@code getObjectType} method
821+
* declared as a raw type, it checks the FactoryBean's {@code getObjectType} method
822822
* on a plain instance of the FactoryBean, without bean properties applied yet.
823-
* If this doesn't return a type yet, and {@code allowInit} is {@code true} a
824-
* full creation of the FactoryBean is used as fallback (through delegation to the
825-
* superclass's implementation).
823+
* If this doesn't return a type yet and {@code allowInit} is {@code true}, full
824+
* creation of the FactoryBean is attempted as fallback (through delegation to the
825+
* superclass implementation).
826826
* <p>The shortcut check for a FactoryBean is only applied in case of a singleton
827827
* FactoryBean. If the FactoryBean instance itself is not kept as singleton,
828828
* 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
@@ -1649,7 +1649,7 @@ protected boolean isFactoryBean(String beanName, RootBeanDefinition mbd) {
16491649
* already. The implementation is allowed to instantiate the target factory bean if
16501650
* {@code allowInit} is {@code true} and the type cannot be determined another way;
16511651
* otherwise it is restricted to introspecting signatures and related metadata.
1652-
* <p>If no {@link FactoryBean#OBJECT_TYPE_ATTRIBUTE} if set on the bean definition
1652+
* <p>If no {@link FactoryBean#OBJECT_TYPE_ATTRIBUTE} is set on the bean definition
16531653
* and {@code allowInit} is {@code true}, the default implementation will create
16541654
* the FactoryBean via {@code getBean} to call its {@code getObjectType} method.
16551655
* 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

+58-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
@@ -105,14 +118,13 @@ public void preFreezeUnresolvedGenericFactoryBean() {
105118
}
106119
}
107120

121+
108122
private void assertPostFreeze(Class<?> configurationClass) {
109-
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
110-
configurationClass);
123+
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(configurationClass);
111124
assertContainsMyBeanName(context);
112125
}
113126

114-
private void assertPreFreeze(Class<?> configurationClass,
115-
BeanFactoryPostProcessor... postProcessors) {
127+
private void assertPreFreeze(Class<?> configurationClass, BeanFactoryPostProcessor... postProcessors) {
116128
NameCollectingBeanFactoryPostProcessor postProcessor = new NameCollectingBeanFactoryPostProcessor();
117129
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
118130
try (context) {
@@ -132,41 +144,38 @@ private void assertContainsMyBeanName(String[] names) {
132144
assertThat(names).containsExactly("myBean");
133145
}
134146

135-
private static class NameCollectingBeanFactoryPostProcessor
136-
implements BeanFactoryPostProcessor {
147+
148+
private static class NameCollectingBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
137149

138150
private String[] names;
139151

140152
@Override
141-
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
142-
throws BeansException {
143-
this.names = beanFactory.getBeanNamesForType(MyBean.class, true, false);
153+
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
154+
ResolvableType typeToMatch = ResolvableType.forClassWithGenerics(MyBean.class, String.class);
155+
this.names = beanFactory.getBeanNamesForType(typeToMatch, true, false);
144156
}
145157

146158
public String[] getNames() {
147159
return this.names;
148160
}
149-
150161
}
151162

152163
@Configuration
153164
static class DirectConfiguration {
154165

155166
@Bean
156-
MyBean myBean() {
157-
return new MyBean();
167+
MyBean<String> myBean() {
168+
return new MyBean<>();
158169
}
159-
160170
}
161171

162172
@Configuration
163173
static class GenericMethodConfiguration {
164174

165175
@Bean
166-
FactoryBean<MyBean> myBean() {
167-
return new TestFactoryBean<>(new MyBean());
176+
FactoryBean<MyBean<String>> myBean() {
177+
return new TestFactoryBean<>(new MyBean<>());
168178
}
169-
170179
}
171180

172181
@Configuration
@@ -176,13 +185,11 @@ static class GenericClassConfiguration {
176185
MyFactoryBean myBean() {
177186
return new MyFactoryBean();
178187
}
179-
180188
}
181189

182190
@Configuration
183191
@Import(AttributeClassRegistrar.class)
184192
static class AttributeClassConfiguration {
185-
186193
}
187194

188195
static class AttributeClassRegistrar implements ImportBeanDefinitionRegistrar {
@@ -191,16 +198,32 @@ static class AttributeClassRegistrar implements ImportBeanDefinitionRegistrar {
191198
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
192199
BeanDefinition definition = BeanDefinitionBuilder.genericBeanDefinition(
193200
RawWithAbstractObjectTypeFactoryBean.class).getBeanDefinition();
194-
definition.setAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE, MyBean.class);
201+
definition.setAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE,
202+
ResolvableType.forClassWithGenerics(MyBean.class, String.class));
195203
registry.registerBeanDefinition("myBean", definition);
196204
}
205+
}
197206

207+
@Configuration
208+
@Import(TargetTypeRegistrar.class)
209+
static class TargetTypeConfiguration {
210+
}
211+
212+
static class TargetTypeRegistrar implements ImportBeanDefinitionRegistrar {
213+
214+
@Override
215+
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
216+
RootBeanDefinition definition = new RootBeanDefinition(RawWithAbstractObjectTypeFactoryBean.class);
217+
definition.setTargetType(ResolvableType.forClassWithGenerics(FactoryBean.class,
218+
ResolvableType.forClassWithGenerics(MyBean.class, String.class)));
219+
registry.registerBeanDefinition("myBean", definition);
220+
}
198221
}
199222

200223
abstract static class AbstractMyBean {
201224
}
202225

203-
static class MyBean extends AbstractMyBean {
226+
static class MyBean<T> extends AbstractMyBean {
204227
}
205228

206229
static class TestFactoryBean<T> implements FactoryBean<T> {
@@ -212,39 +235,34 @@ public TestFactoryBean(T instance) {
212235
}
213236

214237
@Override
215-
public T getObject() throws Exception {
238+
public T getObject() {
216239
return this.instance;
217240
}
218241

219242
@Override
220243
public Class<?> getObjectType() {
221244
return this.instance.getClass();
222245
}
223-
224246
}
225247

226-
static class MyFactoryBean extends TestFactoryBean<MyBean> {
248+
static class MyFactoryBean extends TestFactoryBean<MyBean<String>> {
227249

228250
public MyFactoryBean() {
229-
super(new MyBean());
251+
super(new MyBean<>());
230252
}
231-
232253
}
233254

234255
static class RawWithAbstractObjectTypeFactoryBean implements FactoryBean<Object> {
235256

236-
private final Object object = new MyBean();
237-
238257
@Override
239258
public Object getObject() throws Exception {
240-
return object;
259+
throw new IllegalStateException();
241260
}
242261

243262
@Override
244263
public Class<?> getObjectType() {
245264
return MyBean.class;
246265
}
247-
248266
}
249267

250268
}

0 commit comments

Comments
 (0)