Skip to content

Commit 5938df5

Browse files
committed
Stop auto-config of MethodValidationPP triggering early init
Previously, if a user's configuration class provided a custom Validator bean, that configuration class would be initialized very early so that the Validator could be used to create the auto-configured MethodValidationPostProcessor. This early initialization could problems as it may prevent any of the configuration class's dependencies from being post-processed. This commit updates the injection of the Validator bean to be lazy, thereby preventing the creation of the auto-configured MethodValidationPostProcessor from triggering early initialization. Closes gh-9416
1 parent fb5a3ef commit 5938df5

File tree

2 files changed

+64
-1
lines changed

2 files changed

+64
-1
lines changed

spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/validation/ValidationAutoConfiguration.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.springframework.context.annotation.Bean;
3030
import org.springframework.context.annotation.Configuration;
3131
import org.springframework.context.annotation.Import;
32+
import org.springframework.context.annotation.Lazy;
3233
import org.springframework.context.annotation.Role;
3334
import org.springframework.core.env.Environment;
3435
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
@@ -60,7 +61,7 @@ public static LocalValidatorFactoryBean defaultValidator() {
6061
@Bean
6162
@ConditionalOnMissingBean
6263
public static MethodValidationPostProcessor methodValidationPostProcessor(
63-
Environment environment, Validator validator) {
64+
Environment environment, @Lazy Validator validator) {
6465
MethodValidationPostProcessor processor = new MethodValidationPostProcessor();
6566
processor.setProxyTargetClass(determineProxyTargetClass(environment));
6667
processor.setValidator(validator);

spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/validation/ValidationAutoConfigurationTests.java

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616

1717
package org.springframework.boot.autoconfigure.validation;
1818

19+
import java.util.HashSet;
20+
import java.util.Set;
21+
1922
import javax.validation.ConstraintViolationException;
2023
import javax.validation.Validator;
2124
import javax.validation.constraints.Min;
@@ -27,12 +30,15 @@
2730
import org.junit.rules.ExpectedException;
2831

2932
import org.springframework.beans.DirectFieldAccessor;
33+
import org.springframework.beans.factory.config.BeanPostProcessor;
34+
import org.springframework.boot.autoconfigure.validation.ValidationAutoConfigurationTests.CustomValidatorConfiguration.TestBeanPostProcessor;
3035
import org.springframework.boot.test.util.EnvironmentTestUtils;
3136
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
3237
import org.springframework.context.annotation.Bean;
3338
import org.springframework.context.annotation.Configuration;
3439
import org.springframework.context.annotation.Primary;
3540
import org.springframework.validation.annotation.Validated;
41+
import org.springframework.validation.beanvalidation.CustomValidatorBean;
3642
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
3743
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
3844
import org.springframework.validation.beanvalidation.OptionalValidatorFactoryBean;
@@ -198,6 +204,13 @@ public void userDefinedMethodValidationPostProcessorTakesPrecedence() {
198204
.getPropertyValue("validator"));
199205
}
200206

207+
@Test
208+
public void methodValidationPostProcessorValidatorDependencyDoesNotTriggerEarlyInitialization() {
209+
load(CustomValidatorConfiguration.class);
210+
assertThat(this.context.getBean(TestBeanPostProcessor.class).postProcessed)
211+
.contains("someService");
212+
}
213+
201214
private boolean isPrimaryBean(String beanName) {
202215
return this.context.getBeanDefinition(beanName).isPrimary();
203216
}
@@ -322,4 +335,53 @@ public MethodValidationPostProcessor testMethodValidationPostProcessor() {
322335

323336
}
324337

338+
@org.springframework.context.annotation.Configuration
339+
static class CustomValidatorConfiguration {
340+
341+
CustomValidatorConfiguration(SomeService someService) {
342+
343+
}
344+
345+
@Bean
346+
Validator customValidator() {
347+
return new CustomValidatorBean();
348+
}
349+
350+
@Bean
351+
static TestBeanPostProcessor testBeanPostProcessor() {
352+
return new TestBeanPostProcessor();
353+
}
354+
355+
@Configuration
356+
static class SomeServiceConfiguration {
357+
358+
@Bean
359+
public SomeService someService() {
360+
return new SomeService();
361+
}
362+
363+
}
364+
365+
static class SomeService {
366+
367+
}
368+
369+
static class TestBeanPostProcessor implements BeanPostProcessor {
370+
371+
private Set<String> postProcessed = new HashSet<String>();
372+
373+
@Override
374+
public Object postProcessAfterInitialization(Object bean, String name) {
375+
this.postProcessed.add(name);
376+
return bean;
377+
}
378+
379+
@Override
380+
public Object postProcessBeforeInitialization(Object bean, String name) {
381+
return bean;
382+
}
383+
384+
}
385+
}
386+
325387
}

0 commit comments

Comments
 (0)