diff --git a/framework-docs/modules/ROOT/pages/data-access/jdbc/advanced.adoc b/framework-docs/modules/ROOT/pages/data-access/jdbc/advanced.adoc index 04533c9cb8..6aeb504a0f 100644 --- a/framework-docs/modules/ROOT/pages/data-access/jdbc/advanced.adoc +++ b/framework-docs/modules/ROOT/pages/data-access/jdbc/advanced.adoc @@ -211,19 +211,20 @@ the JDBC driver. If the count is not available, the JDBC driver returns a value ==== In such a scenario, with automatic setting of values on an underlying `PreparedStatement`, the corresponding JDBC type for each value needs to be derived from the given Java type. -While this usually works well, there is a potential for issues (for example, with Map-contained -`null` values). Spring, by default, calls `ParameterMetaData.getParameterType` in such a -case, which can be expensive with your JDBC driver. You should use a recent driver +While this usually works well, there is a potential for issues (for example, with +Map-contained `null` values). Spring, by default, calls `ParameterMetaData.getParameterType` +in such a case, which can be expensive with your JDBC driver. You should use a recent driver version and consider setting the `spring.jdbc.getParameterType.ignore` property to `true` (as a JVM system property or via the -xref:appendix.adoc#appendix-spring-properties[`SpringProperties`] mechanism) if you encounter -a performance issue (as reported on Oracle 12c, JBoss, and PostgreSQL). +xref:appendix.adoc#appendix-spring-properties[`SpringProperties`] mechanism) +if you encounter a specific performance issue for your application. -Alternatively, you might consider specifying the corresponding JDBC types explicitly, -either through a `BatchPreparedStatementSetter` (as shown earlier), through an explicit type -array given to a `List` based call, through `registerSqlType` calls on a -custom `MapSqlParameterSource` instance, or through a `BeanPropertySqlParameterSource` -that derives the SQL type from the Java-declared property type even for a null value. +Alternatively, you could consider specifying the corresponding JDBC types explicitly, +either through a `BatchPreparedStatementSetter` (as shown earlier), through an explicit +type array given to a `List` based call, through `registerSqlType` calls on a +custom `MapSqlParameterSource` instance, through a `BeanPropertySqlParameterSource` +that derives the SQL type from the Java-declared property type even for a null value, or +through providing individual `SqlParameterValue` instances instead of plain null values. ==== diff --git a/spring-aop/src/main/java/org/springframework/aop/scope/ScopedProxyBeanRegistrationAotProcessor.java b/spring-aop/src/main/java/org/springframework/aop/scope/ScopedProxyBeanRegistrationAotProcessor.java index dbf2df4fa1..05906fd903 100644 --- a/spring-aop/src/main/java/org/springframework/aop/scope/ScopedProxyBeanRegistrationAotProcessor.java +++ b/spring-aop/src/main/java/org/springframework/aop/scope/ScopedProxyBeanRegistrationAotProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2023 the original author or authors. + * Copyright 2002-2024 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. @@ -54,6 +54,7 @@ class ScopedProxyBeanRegistrationAotProcessor implements BeanRegistrationAotProc @Override + @Nullable public BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) { Class beanClass = registeredBean.getBeanClass(); if (beanClass.equals(ScopedProxyFactoryBean.class)) { @@ -79,8 +80,8 @@ class ScopedProxyBeanRegistrationAotProcessor implements BeanRegistrationAotProc } @Nullable - private BeanDefinition getTargetBeanDefinition(ConfigurableBeanFactory beanFactory, - @Nullable String targetBeanName) { + private BeanDefinition getTargetBeanDefinition( + ConfigurableBeanFactory beanFactory, @Nullable String targetBeanName) { if (targetBeanName != null && beanFactory.containsBean(targetBeanName)) { return beanFactory.getMergedBeanDefinition(targetBeanName); @@ -123,42 +124,32 @@ class ScopedProxyBeanRegistrationAotProcessor implements BeanRegistrationAotProc @Override public CodeBlock generateSetBeanDefinitionPropertiesCode( - GenerationContext generationContext, - BeanRegistrationCode beanRegistrationCode, + GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode, RootBeanDefinition beanDefinition, Predicate attributeFilter) { - RootBeanDefinition processedBeanDefinition = new RootBeanDefinition( - beanDefinition); - processedBeanDefinition - .setTargetType(this.targetBeanDefinition.getResolvableType()); - processedBeanDefinition.getPropertyValues() - .removePropertyValue("targetBeanName"); + RootBeanDefinition processedBeanDefinition = new RootBeanDefinition(beanDefinition); + processedBeanDefinition.setTargetType(this.targetBeanDefinition.getResolvableType()); + processedBeanDefinition.getPropertyValues().removePropertyValue("targetBeanName"); return super.generateSetBeanDefinitionPropertiesCode(generationContext, beanRegistrationCode, processedBeanDefinition, attributeFilter); } @Override - public CodeBlock generateInstanceSupplierCode(GenerationContext generationContext, - BeanRegistrationCode beanRegistrationCode, - Executable constructorOrFactoryMethod, - boolean allowDirectSupplierShortcut) { + public CodeBlock generateInstanceSupplierCode( + GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode, + Executable constructorOrFactoryMethod, boolean allowDirectSupplierShortcut) { GeneratedMethod generatedMethod = beanRegistrationCode.getMethods() .add("getScopedProxyInstance", method -> { - method.addJavadoc( - "Create the scoped proxy bean instance for '$L'.", + method.addJavadoc("Create the scoped proxy bean instance for '$L'.", this.registeredBean.getBeanName()); method.addModifiers(Modifier.PRIVATE, Modifier.STATIC); method.returns(ScopedProxyFactoryBean.class); - method.addParameter(RegisteredBean.class, - REGISTERED_BEAN_PARAMETER_NAME); + method.addParameter(RegisteredBean.class, REGISTERED_BEAN_PARAMETER_NAME); method.addStatement("$T factory = new $T()", - ScopedProxyFactoryBean.class, - ScopedProxyFactoryBean.class); - method.addStatement("factory.setTargetBeanName($S)", - this.targetBeanName); - method.addStatement( - "factory.setBeanFactory($L.getBeanFactory())", + ScopedProxyFactoryBean.class, ScopedProxyFactoryBean.class); + method.addStatement("factory.setTargetBeanName($S)", this.targetBeanName); + method.addStatement("factory.setBeanFactory($L.getBeanFactory())", REGISTERED_BEAN_PARAMETER_NAME); method.addStatement("return factory"); }); diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationCodeFragmentsDecorator.java b/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationCodeFragmentsDecorator.java index e4ff961262..37f610f5af 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationCodeFragmentsDecorator.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationCodeFragmentsDecorator.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2024 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. @@ -59,40 +59,39 @@ public class BeanRegistrationCodeFragmentsDecorator implements BeanRegistrationC public CodeBlock generateNewBeanDefinitionCode(GenerationContext generationContext, ResolvableType beanType, BeanRegistrationCode beanRegistrationCode) { - return this.delegate.generateNewBeanDefinitionCode(generationContext, - beanType, beanRegistrationCode); + return this.delegate.generateNewBeanDefinitionCode(generationContext, beanType, beanRegistrationCode); } @Override - public CodeBlock generateSetBeanDefinitionPropertiesCode(GenerationContext generationContext, - BeanRegistrationCode beanRegistrationCode, RootBeanDefinition beanDefinition, - Predicate attributeFilter) { + public CodeBlock generateSetBeanDefinitionPropertiesCode( + GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode, + RootBeanDefinition beanDefinition, Predicate attributeFilter) { return this.delegate.generateSetBeanDefinitionPropertiesCode( generationContext, beanRegistrationCode, beanDefinition, attributeFilter); } @Override - public CodeBlock generateSetBeanInstanceSupplierCode(GenerationContext generationContext, - BeanRegistrationCode beanRegistrationCode, CodeBlock instanceSupplierCode, - List postProcessors) { + public CodeBlock generateSetBeanInstanceSupplierCode( + GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode, + CodeBlock instanceSupplierCode, List postProcessors) { return this.delegate.generateSetBeanInstanceSupplierCode(generationContext, beanRegistrationCode, instanceSupplierCode, postProcessors); } @Override - public CodeBlock generateInstanceSupplierCode(GenerationContext generationContext, - BeanRegistrationCode beanRegistrationCode, Executable constructorOrFactoryMethod, - boolean allowDirectSupplierShortcut) { + public CodeBlock generateInstanceSupplierCode( + GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode, + Executable constructorOrFactoryMethod, boolean allowDirectSupplierShortcut) { return this.delegate.generateInstanceSupplierCode(generationContext, beanRegistrationCode, constructorOrFactoryMethod, allowDirectSupplierShortcut); } @Override - public CodeBlock generateReturnCode(GenerationContext generationContext, - BeanRegistrationCode beanRegistrationCode) { + public CodeBlock generateReturnCode( + GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode) { return this.delegate.generateReturnCode(generationContext, beanRegistrationCode); } 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 d5281ef6ca..c3978fe3e3 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2023 the original author or authors. + * Copyright 2002-2024 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. @@ -41,8 +41,7 @@ import org.springframework.util.Assert; import org.springframework.util.ClassUtils; /** - * Internal {@link BeanRegistrationCodeFragments} implementation used by - * default. + * Internal {@link BeanRegistrationCodeFragments} implementation used by default. * * @author Phillip Webb */ @@ -55,8 +54,8 @@ class DefaultBeanRegistrationCodeFragments implements BeanRegistrationCodeFragme private final BeanDefinitionMethodGeneratorFactory beanDefinitionMethodGeneratorFactory; - DefaultBeanRegistrationCodeFragments(BeanRegistrationsCode beanRegistrationsCode, - RegisteredBean registeredBean, + DefaultBeanRegistrationCodeFragments( + BeanRegistrationsCode beanRegistrationsCode, RegisteredBean registeredBean, BeanDefinitionMethodGeneratorFactory beanDefinitionMethodGeneratorFactory) { this.beanRegistrationsCode = beanRegistrationsCode; @@ -66,9 +65,7 @@ class DefaultBeanRegistrationCodeFragments implements BeanRegistrationCodeFragme @Override - public ClassName getTarget(RegisteredBean registeredBean, - Executable constructorOrFactoryMethod) { - + public ClassName getTarget(RegisteredBean registeredBean, Executable constructorOrFactoryMethod) { Class target = extractDeclaringClass(registeredBean.getBeanType(), constructorOrFactoryMethod); while (target.getName().startsWith("java.") && registeredBean.isInnerBean()) { RegisteredBean parent = registeredBean.getParent(); @@ -80,9 +77,8 @@ class DefaultBeanRegistrationCodeFragments implements BeanRegistrationCodeFragme private Class extractDeclaringClass(ResolvableType beanType, Executable executable) { Class declaringClass = ClassUtils.getUserClass(executable.getDeclaringClass()); - if (executable instanceof Constructor - && AccessControl.forMember(executable).isPublic() - && FactoryBean.class.isAssignableFrom(declaringClass)) { + if (executable instanceof Constructor && AccessControl.forMember(executable).isPublic() && + FactoryBean.class.isAssignableFrom(declaringClass)) { return extractTargetClassFromFactoryBean(declaringClass, beanType); } return executable.getDeclaringClass(); @@ -91,8 +87,7 @@ class DefaultBeanRegistrationCodeFragments implements BeanRegistrationCodeFragme /** * Extract the target class of a public {@link FactoryBean} based on its * constructor. If the implementation does not resolve the target class - * because it itself uses a generic, attempt to extract it from the - * bean type. + * because it itself uses a generic, attempt to extract it from the bean type. * @param factoryBeanType the factory bean type * @param beanType the bean type * @return the target class to use @@ -113,17 +108,15 @@ class DefaultBeanRegistrationCodeFragments implements BeanRegistrationCodeFragme ResolvableType beanType, BeanRegistrationCode beanRegistrationCode) { CodeBlock.Builder code = CodeBlock.builder(); - RootBeanDefinition mergedBeanDefinition = this.registeredBean.getMergedBeanDefinition(); - Class beanClass = (mergedBeanDefinition.hasBeanClass() - ? ClassUtils.getUserClass(mergedBeanDefinition.getBeanClass()) : null); + RootBeanDefinition mbd = this.registeredBean.getMergedBeanDefinition(); + Class beanClass = (mbd.hasBeanClass() ? ClassUtils.getUserClass(mbd.getBeanClass()) : null); CodeBlock beanClassCode = generateBeanClassCode( beanRegistrationCode.getClassName().packageName(), (beanClass != null ? beanClass : beanType.toClass())); code.addStatement("$T $L = new $T($L)", RootBeanDefinition.class, BEAN_DEFINITION_VARIABLE, RootBeanDefinition.class, beanClassCode); if (targetTypeNecessary(beanType, beanClass)) { - code.addStatement("$L.setTargetType($L)", BEAN_DEFINITION_VARIABLE, - generateBeanTypeCode(beanType)); + code.addStatement("$L.setTargetType($L)", BEAN_DEFINITION_VARIABLE, generateBeanTypeCode(beanType)); } return code.build(); } @@ -148,8 +141,7 @@ class DefaultBeanRegistrationCodeFragments implements BeanRegistrationCodeFragme if (beanType.hasGenerics()) { return true; } - if (beanClass != null - && this.registeredBean.getMergedBeanDefinition().getFactoryMethodName() != null) { + if (beanClass != null && this.registeredBean.getMergedBeanDefinition().getFactoryMethodName() != null) { return true; } return (beanClass != null && !beanType.toClass().equals(beanClass)); @@ -157,9 +149,8 @@ class DefaultBeanRegistrationCodeFragments implements BeanRegistrationCodeFragme @Override public CodeBlock generateSetBeanDefinitionPropertiesCode( - GenerationContext generationContext, - BeanRegistrationCode beanRegistrationCode, RootBeanDefinition beanDefinition, - Predicate attributeFilter) { + GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode, + RootBeanDefinition beanDefinition, Predicate attributeFilter) { return new BeanDefinitionPropertiesCodeGenerator( generationContext.getRuntimeHints(), attributeFilter, @@ -169,9 +160,7 @@ class DefaultBeanRegistrationCodeFragments implements BeanRegistrationCodeFragme } @Nullable - protected CodeBlock generateValueCode(GenerationContext generationContext, - String name, Object value) { - + protected CodeBlock generateValueCode(GenerationContext generationContext, String name, Object value) { RegisteredBean innerRegisteredBean = getInnerRegisteredBean(value); if (innerRegisteredBean != null) { BeanDefinitionMethodGenerator methodGenerator = this.beanDefinitionMethodGeneratorFactory @@ -197,9 +186,8 @@ class DefaultBeanRegistrationCodeFragments implements BeanRegistrationCodeFragme @Override public CodeBlock generateSetBeanInstanceSupplierCode( - GenerationContext generationContext, - BeanRegistrationCode beanRegistrationCode, CodeBlock instanceSupplierCode, - List postProcessors) { + GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode, + CodeBlock instanceSupplierCode, List postProcessors) { CodeBlock.Builder code = CodeBlock.builder(); if (postProcessors.isEmpty()) { @@ -219,8 +207,8 @@ class DefaultBeanRegistrationCodeFragments implements BeanRegistrationCodeFragme } @Override - public CodeBlock generateInstanceSupplierCode(GenerationContext generationContext, - BeanRegistrationCode beanRegistrationCode, + public CodeBlock generateInstanceSupplierCode( + GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode, Executable constructorOrFactoryMethod, boolean allowDirectSupplierShortcut) { return new InstanceSupplierCodeGenerator(generationContext, @@ -229,8 +217,8 @@ class DefaultBeanRegistrationCodeFragments implements BeanRegistrationCodeFragme } @Override - public CodeBlock generateReturnCode(GenerationContext generationContext, - BeanRegistrationCode beanRegistrationCode) { + public CodeBlock generateReturnCode( + GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode) { CodeBlock.Builder code = CodeBlock.builder(); code.addStatement("return $L", BEAN_DEFINITION_VARIABLE); diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java index 4eb4a5809f..6e70c3d081 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java @@ -737,12 +737,7 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo } private CodeBlock handleNull(@Nullable Object value, Supplier nonNull) { - if (value == null) { - return CodeBlock.of("null"); - } - else { - return nonNull.get(); - } + return (value == null ? CodeBlock.of("null") : nonNull.get()); } } @@ -757,8 +752,9 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo } @Override - public CodeBlock generateSetBeanDefinitionPropertiesCode(GenerationContext generationContext, - BeanRegistrationCode beanRegistrationCode, RootBeanDefinition beanDefinition, Predicate attributeFilter) { + public CodeBlock generateSetBeanDefinitionPropertiesCode( + GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode, + RootBeanDefinition beanDefinition, Predicate attributeFilter) { CodeBlock.Builder code = CodeBlock.builder(); code.add(super.generateSetBeanDefinitionPropertiesCode(generationContext, @@ -769,9 +765,9 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo } @Override - public CodeBlock generateInstanceSupplierCode(GenerationContext generationContext, - BeanRegistrationCode beanRegistrationCode, Executable constructorOrFactoryMethod, - boolean allowDirectSupplierShortcut) { + public CodeBlock generateInstanceSupplierCode( + GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode, + Executable constructorOrFactoryMethod, boolean allowDirectSupplierShortcut) { Executable executableToUse = proxyExecutable(generationContext.getRuntimeHints(), constructorOrFactoryMethod); return super.generateInstanceSupplierCode(generationContext, beanRegistrationCode,