Skip to content

Commit a9efe10

Browse files
committed
Merge branch '6.1.x'
# Conflicts: # spring-beans/src/main/java/org/springframework/beans/factory/aot/DefaultBeanRegistrationCodeFragments.java
2 parents bb64e22 + 3ccaefe commit a9efe10

File tree

6 files changed

+73
-77
lines changed

6 files changed

+73
-77
lines changed

framework-docs/modules/ROOT/pages/data-access/jdbc/advanced.adoc

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -211,19 +211,28 @@ the JDBC driver. If the count is not available, the JDBC driver returns a value
211211
====
212212
In such a scenario, with automatic setting of values on an underlying `PreparedStatement`,
213213
the corresponding JDBC type for each value needs to be derived from the given Java type.
214-
While this usually works well, there is a potential for issues (for example, with Map-contained
215-
`null` values). Spring, by default, calls `ParameterMetaData.getParameterType` in such a
216-
case, which can be expensive with your JDBC driver. You should use a recent driver
214+
While this usually works well, there is a potential for issues (for example, with
215+
Map-contained `null` values). Spring, by default, calls `ParameterMetaData.getParameterType`
216+
in such a case, which can be expensive with your JDBC driver. You should use a recent driver
217217
version and consider setting the `spring.jdbc.getParameterType.ignore` property to `true`
218218
(as a JVM system property or via the
219-
xref:appendix.adoc#appendix-spring-properties[`SpringProperties`] mechanism) if you encounter
220-
a performance issue (as reported on Oracle 12c, JBoss, and PostgreSQL).
221-
222-
Alternatively, you might consider specifying the corresponding JDBC types explicitly,
223-
either through a `BatchPreparedStatementSetter` (as shown earlier), through an explicit type
224-
array given to a `List<Object[]>` based call, through `registerSqlType` calls on a
225-
custom `MapSqlParameterSource` instance, or through a `BeanPropertySqlParameterSource`
226-
that derives the SQL type from the Java-declared property type even for a null value.
219+
xref:appendix.adoc#appendix-spring-properties[`SpringProperties`] mechanism)
220+
if you encounter a specific performance issue for your application.
221+
222+
As of 6.1.2, Spring bypasses the default `getParameterType` resolution on PostgreSQL and
223+
MS SQL Server. This is a common optimization to avoid further roundtrips to the DBMS just
224+
for parameter type resolution which is known to make a very significant difference on
225+
PostgreSQL and MS SQL Server specifically, in particular for batch operations. If you
226+
happen to see a side effect e.g. when setting a byte array to null without specific type
227+
indication, you may explicitly set the `spring.jdbc.getParameterType.ignore=false` flag
228+
as a system property (see above) to restore full `getParameterType` resolution.
229+
230+
Alternatively, you could consider specifying the corresponding JDBC types explicitly,
231+
either through a `BatchPreparedStatementSetter` (as shown earlier), through an explicit
232+
type array given to a `List<Object[]>` based call, through `registerSqlType` calls on a
233+
custom `MapSqlParameterSource` instance, through a `BeanPropertySqlParameterSource`
234+
that derives the SQL type from the Java-declared property type even for a null value, or
235+
through providing individual `SqlParameterValue` instances instead of plain null values.
227236
====
228237

229238

spring-aop/src/main/java/org/springframework/aop/scope/ScopedProxyBeanRegistrationAotProcessor.java

Lines changed: 12 additions & 21 deletions
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.
@@ -80,8 +80,8 @@ private String getTargetBeanName(BeanDefinition beanDefinition) {
8080
}
8181

8282
@Nullable
83-
private BeanDefinition getTargetBeanDefinition(ConfigurableBeanFactory beanFactory,
84-
@Nullable String targetBeanName) {
83+
private BeanDefinition getTargetBeanDefinition(
84+
ConfigurableBeanFactory beanFactory, @Nullable String targetBeanName) {
8585

8686
if (targetBeanName != null && beanFactory.containsBean(targetBeanName)) {
8787
return beanFactory.getMergedBeanDefinition(targetBeanName);
@@ -124,16 +124,12 @@ public CodeBlock generateNewBeanDefinitionCode(GenerationContext generationConte
124124

125125
@Override
126126
public CodeBlock generateSetBeanDefinitionPropertiesCode(
127-
GenerationContext generationContext,
128-
BeanRegistrationCode beanRegistrationCode,
127+
GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode,
129128
RootBeanDefinition beanDefinition, Predicate<String> attributeFilter) {
130129

131-
RootBeanDefinition processedBeanDefinition = new RootBeanDefinition(
132-
beanDefinition);
133-
processedBeanDefinition
134-
.setTargetType(this.targetBeanDefinition.getResolvableType());
135-
processedBeanDefinition.getPropertyValues()
136-
.removePropertyValue("targetBeanName");
130+
RootBeanDefinition processedBeanDefinition = new RootBeanDefinition(beanDefinition);
131+
processedBeanDefinition.setTargetType(this.targetBeanDefinition.getResolvableType());
132+
processedBeanDefinition.getPropertyValues().removePropertyValue("targetBeanName");
137133
return super.generateSetBeanDefinitionPropertiesCode(generationContext,
138134
beanRegistrationCode, processedBeanDefinition, attributeFilter);
139135
}
@@ -144,20 +140,15 @@ public CodeBlock generateInstanceSupplierCode(GenerationContext generationContex
144140

145141
GeneratedMethod generatedMethod = beanRegistrationCode.getMethods()
146142
.add("getScopedProxyInstance", method -> {
147-
method.addJavadoc(
148-
"Create the scoped proxy bean instance for '$L'.",
143+
method.addJavadoc("Create the scoped proxy bean instance for '$L'.",
149144
this.registeredBean.getBeanName());
150145
method.addModifiers(Modifier.PRIVATE, Modifier.STATIC);
151146
method.returns(ScopedProxyFactoryBean.class);
152-
method.addParameter(RegisteredBean.class,
153-
REGISTERED_BEAN_PARAMETER_NAME);
147+
method.addParameter(RegisteredBean.class, REGISTERED_BEAN_PARAMETER_NAME);
154148
method.addStatement("$T factory = new $T()",
155-
ScopedProxyFactoryBean.class,
156-
ScopedProxyFactoryBean.class);
157-
method.addStatement("factory.setTargetBeanName($S)",
158-
this.targetBeanName);
159-
method.addStatement(
160-
"factory.setBeanFactory($L.getBeanFactory())",
149+
ScopedProxyFactoryBean.class, ScopedProxyFactoryBean.class);
150+
method.addStatement("factory.setTargetBeanName($S)", this.targetBeanName);
151+
method.addStatement("factory.setBeanFactory($L.getBeanFactory())",
161152
REGISTERED_BEAN_PARAMETER_NAME);
162153
method.addStatement("return factory");
163154
});

spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1098,7 +1098,6 @@ private void registerProxyIfNecessary(RuntimeHints runtimeHints, DependencyDescr
10981098
}
10991099
}
11001100
}
1101-
11021101
}
11031102

11041103
}

spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationCodeFragmentsDecorator.java

Lines changed: 13 additions & 13 deletions
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.
@@ -58,39 +58,39 @@ public ClassName getTarget(RegisteredBean registeredBean) {
5858
public CodeBlock generateNewBeanDefinitionCode(GenerationContext generationContext,
5959
ResolvableType beanType, BeanRegistrationCode beanRegistrationCode) {
6060

61-
return this.delegate.generateNewBeanDefinitionCode(generationContext,
62-
beanType, beanRegistrationCode);
61+
return this.delegate.generateNewBeanDefinitionCode(generationContext, beanType, beanRegistrationCode);
6362
}
6463

6564
@Override
66-
public CodeBlock generateSetBeanDefinitionPropertiesCode(GenerationContext generationContext,
67-
BeanRegistrationCode beanRegistrationCode, RootBeanDefinition beanDefinition,
68-
Predicate<String> attributeFilter) {
65+
public CodeBlock generateSetBeanDefinitionPropertiesCode(
66+
GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode,
67+
RootBeanDefinition beanDefinition, Predicate<String> attributeFilter) {
6968

7069
return this.delegate.generateSetBeanDefinitionPropertiesCode(
7170
generationContext, beanRegistrationCode, beanDefinition, attributeFilter);
7271
}
7372

7473
@Override
75-
public CodeBlock generateSetBeanInstanceSupplierCode(GenerationContext generationContext,
76-
BeanRegistrationCode beanRegistrationCode, CodeBlock instanceSupplierCode,
77-
List<MethodReference> postProcessors) {
74+
public CodeBlock generateSetBeanInstanceSupplierCode(
75+
GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode,
76+
CodeBlock instanceSupplierCode, List<MethodReference> postProcessors) {
7877

7978
return this.delegate.generateSetBeanInstanceSupplierCode(generationContext,
8079
beanRegistrationCode, instanceSupplierCode, postProcessors);
8180
}
8281

8382
@Override
84-
public CodeBlock generateInstanceSupplierCode(GenerationContext generationContext,
85-
BeanRegistrationCode beanRegistrationCode, boolean allowDirectSupplierShortcut) {
83+
public CodeBlock generateInstanceSupplierCode(
84+
GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode,
85+
boolean allowDirectSupplierShortcut) {
8686

8787
return this.delegate.generateInstanceSupplierCode(generationContext,
8888
beanRegistrationCode, allowDirectSupplierShortcut);
8989
}
9090

9191
@Override
92-
public CodeBlock generateReturnCode(GenerationContext generationContext,
93-
BeanRegistrationCode beanRegistrationCode) {
92+
public CodeBlock generateReturnCode(
93+
GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode) {
9494

9595
return this.delegate.generateReturnCode(generationContext, beanRegistrationCode);
9696
}

spring-beans/src/main/java/org/springframework/beans/factory/aot/DefaultBeanRegistrationCodeFragments.java

Lines changed: 23 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,7 @@
4646
import org.springframework.util.function.SingletonSupplier;
4747

4848
/**
49-
* Internal {@link BeanRegistrationCodeFragments} implementation used by
50-
* default.
49+
* Internal {@link BeanRegistrationCodeFragments} implementation used by default.
5150
*
5251
* @author Phillip Webb
5352
* @author Stephane Nicoll
@@ -92,9 +91,8 @@ public ClassName getTarget(RegisteredBean registeredBean) {
9291

9392
private Class<?> extractDeclaringClass(RegisteredBean registeredBean, InstantiationDescriptor instantiationDescriptor) {
9493
Class<?> declaringClass = ClassUtils.getUserClass(instantiationDescriptor.targetClass());
95-
if (instantiationDescriptor.executable() instanceof Constructor<?>
96-
&& AccessControl.forMember(instantiationDescriptor.executable()).isPublic()
97-
&& FactoryBean.class.isAssignableFrom(declaringClass)) {
94+
if (instantiationDescriptor.executable() instanceof Constructor<?> ctor &&
95+
AccessControl.forMember(ctor).isPublic() && FactoryBean.class.isAssignableFrom(declaringClass)) {
9896
return extractTargetClassFromFactoryBean(declaringClass, registeredBean.getBeanType());
9997
}
10098
return declaringClass;
@@ -125,17 +123,15 @@ public CodeBlock generateNewBeanDefinitionCode(GenerationContext generationConte
125123
ResolvableType beanType, BeanRegistrationCode beanRegistrationCode) {
126124

127125
CodeBlock.Builder code = CodeBlock.builder();
128-
RootBeanDefinition mergedBeanDefinition = this.registeredBean.getMergedBeanDefinition();
129-
Class<?> beanClass = (mergedBeanDefinition.hasBeanClass()
130-
? ClassUtils.getUserClass(mergedBeanDefinition.getBeanClass()) : null);
126+
RootBeanDefinition mbd = this.registeredBean.getMergedBeanDefinition();
127+
Class<?> beanClass = (mbd.hasBeanClass() ? ClassUtils.getUserClass(mbd.getBeanClass()) : null);
131128
CodeBlock beanClassCode = generateBeanClassCode(
132129
beanRegistrationCode.getClassName().packageName(),
133130
(beanClass != null ? beanClass : beanType.toClass()));
134131
code.addStatement("$T $L = new $T($L)", RootBeanDefinition.class,
135132
BEAN_DEFINITION_VARIABLE, RootBeanDefinition.class, beanClassCode);
136133
if (targetTypeNecessary(beanType, beanClass)) {
137-
code.addStatement("$L.setTargetType($L)", BEAN_DEFINITION_VARIABLE,
138-
generateBeanTypeCode(beanType));
134+
code.addStatement("$L.setTargetType($L)", BEAN_DEFINITION_VARIABLE, generateBeanTypeCode(beanType));
139135
}
140136
return code.build();
141137
}
@@ -160,30 +156,27 @@ private boolean targetTypeNecessary(ResolvableType beanType, @Nullable Class<?>
160156
if (beanType.hasGenerics()) {
161157
return true;
162158
}
163-
if (beanClass != null
164-
&& this.registeredBean.getMergedBeanDefinition().getFactoryMethodName() != null) {
159+
if (beanClass != null && this.registeredBean.getMergedBeanDefinition().getFactoryMethodName() != null) {
165160
return true;
166161
}
167162
return (beanClass != null && !beanType.toClass().equals(beanClass));
168163
}
169164

170165
@Override
171166
public CodeBlock generateSetBeanDefinitionPropertiesCode(
172-
GenerationContext generationContext,
173-
BeanRegistrationCode beanRegistrationCode, RootBeanDefinition beanDefinition,
174-
Predicate<String> attributeFilter) {
167+
GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode,
168+
RootBeanDefinition beanDefinition, Predicate<String> attributeFilter) {
169+
175170
Loader loader = AotServices.factories(this.registeredBean.getBeanFactory().getBeanClassLoader());
176171
List<Delegate> additionalDelegates = loader.load(Delegate.class).asList();
177172
return new BeanDefinitionPropertiesCodeGenerator(generationContext.getRuntimeHints(),
178173
attributeFilter, beanRegistrationCode.getMethods(),
179-
additionalDelegates, (name, value) -> generateValueCode(generationContext, name, value)
180-
).generateCode(beanDefinition);
174+
additionalDelegates, (name, value) -> generateValueCode(generationContext, name, value))
175+
.generateCode(beanDefinition);
181176
}
182177

183178
@Nullable
184-
protected CodeBlock generateValueCode(GenerationContext generationContext,
185-
String name, Object value) {
186-
179+
protected CodeBlock generateValueCode(GenerationContext generationContext, String name, Object value) {
187180
RegisteredBean innerRegisteredBean = getInnerRegisteredBean(value);
188181
if (innerRegisteredBean != null) {
189182
BeanDefinitionMethodGenerator methodGenerator = this.beanDefinitionMethodGeneratorFactory
@@ -209,9 +202,8 @@ private RegisteredBean getInnerRegisteredBean(Object value) {
209202

210203
@Override
211204
public CodeBlock generateSetBeanInstanceSupplierCode(
212-
GenerationContext generationContext,
213-
BeanRegistrationCode beanRegistrationCode, CodeBlock instanceSupplierCode,
214-
List<MethodReference> postProcessors) {
205+
GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode,
206+
CodeBlock instanceSupplierCode, List<MethodReference> postProcessors) {
215207

216208
CodeBlock.Builder code = CodeBlock.builder();
217209
if (postProcessors.isEmpty()) {
@@ -231,19 +223,21 @@ public CodeBlock generateSetBeanInstanceSupplierCode(
231223
}
232224

233225
@Override
234-
public CodeBlock generateInstanceSupplierCode(GenerationContext generationContext,
235-
BeanRegistrationCode beanRegistrationCode, boolean allowDirectSupplierShortcut) {
226+
public CodeBlock generateInstanceSupplierCode(
227+
GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode,
228+
boolean allowDirectSupplierShortcut) {
229+
236230
if (hasInstanceSupplier()) {
237231
throw new AotBeanProcessingException(this.registeredBean, "instance supplier is not supported");
238232
}
239233
return new InstanceSupplierCodeGenerator(generationContext, beanRegistrationCode.getClassName(),
240-
beanRegistrationCode.getMethods(), allowDirectSupplierShortcut).generateCode(
241-
this.registeredBean, this.instantiationDescriptor.get());
234+
beanRegistrationCode.getMethods(), allowDirectSupplierShortcut)
235+
.generateCode(this.registeredBean, this.instantiationDescriptor.get());
242236
}
243237

244238
@Override
245-
public CodeBlock generateReturnCode(GenerationContext generationContext,
246-
BeanRegistrationCode beanRegistrationCode) {
239+
public CodeBlock generateReturnCode(
240+
GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode) {
247241

248242
CodeBlock.Builder code = CodeBlock.builder();
249243
code.addStatement("return $L", BEAN_DEFINITION_VARIABLE);

spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -787,7 +787,8 @@ public ConfigurationClassProxyBeanRegistrationCodeFragments(
787787

788788
@Override
789789
public CodeBlock generateSetBeanDefinitionPropertiesCode(GenerationContext generationContext,
790-
BeanRegistrationCode beanRegistrationCode, RootBeanDefinition beanDefinition, Predicate<String> attributeFilter) {
790+
BeanRegistrationCode beanRegistrationCode, RootBeanDefinition beanDefinition,
791+
Predicate<String> attributeFilter) {
791792

792793
CodeBlock.Builder code = CodeBlock.builder();
793794
code.add(super.generateSetBeanDefinitionPropertiesCode(generationContext,
@@ -808,7 +809,9 @@ public CodeBlock generateInstanceSupplierCode(GenerationContext generationContex
808809
.generateCode(this.registeredBean, instantiationDescriptor);
809810
}
810811

811-
private InstantiationDescriptor proxyInstantiationDescriptor(RuntimeHints runtimeHints, InstantiationDescriptor instantiationDescriptor) {
812+
private InstantiationDescriptor proxyInstantiationDescriptor(
813+
RuntimeHints runtimeHints, InstantiationDescriptor instantiationDescriptor) {
814+
812815
Executable userExecutable = instantiationDescriptor.executable();
813816
if (userExecutable instanceof Constructor<?> userConstructor) {
814817
try {

0 commit comments

Comments
 (0)