Null out validator in ContextRefreshedEvent
This is an optimization that recognizes the need for Hibernate validator to cache reflection data, but also that we don't need it after the bulk of the work has been done on context refresh. Fixes gh-4734
This commit is contained in:
parent
bdc395f16e
commit
e8632d9feb
|
|
@ -36,9 +36,11 @@ import org.springframework.boot.bind.PropertiesConfigurationFactory;
|
|||
import org.springframework.boot.env.PropertySourcesLoader;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.context.ResourceLoaderAware;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.PriorityOrdered;
|
||||
|
|
@ -71,9 +73,10 @@ import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
|
|||
* @author Christian Dupuis
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class ConfigurationPropertiesBindingPostProcessor implements BeanPostProcessor,
|
||||
BeanFactoryAware, ResourceLoaderAware, EnvironmentAware, ApplicationContextAware,
|
||||
InitializingBean, DisposableBean, PriorityOrdered {
|
||||
public class ConfigurationPropertiesBindingPostProcessor
|
||||
implements BeanPostProcessor, BeanFactoryAware, ResourceLoaderAware,
|
||||
EnvironmentAware, ApplicationContextAware, InitializingBean, DisposableBean,
|
||||
ApplicationListener<ContextRefreshedEvent>, PriorityOrdered {
|
||||
|
||||
/**
|
||||
* The bean name of the configuration properties validator.
|
||||
|
|
@ -87,7 +90,7 @@ public class ConfigurationPropertiesBindingPostProcessor implements BeanPostProc
|
|||
|
||||
private PropertySources propertySources;
|
||||
|
||||
private Validator validator;
|
||||
private volatile Validator validator;
|
||||
|
||||
private boolean ownedValidator = false;
|
||||
|
||||
|
|
@ -192,6 +195,22 @@ public class ConfigurationPropertiesBindingPostProcessor implements BeanPostProc
|
|||
if (this.propertySources == null) {
|
||||
this.propertySources = deducePropertySources();
|
||||
}
|
||||
initializeValidator();
|
||||
if (this.conversionService == null) {
|
||||
this.conversionService = getOptionalBean(
|
||||
ConfigurableApplicationContext.CONVERSION_SERVICE_BEAN_NAME,
|
||||
ConversionService.class);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ContextRefreshedEvent event) {
|
||||
if (this.validator != null && isJsr303Present()) {
|
||||
this.validator = null; // allow it to be garbage collected
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeValidator() {
|
||||
if (this.validator == null) {
|
||||
this.validator = getOptionalBean(VALIDATOR_BEAN_NAME, Validator.class);
|
||||
if (this.validator == null && isJsr303Present()) {
|
||||
|
|
@ -200,11 +219,6 @@ public class ConfigurationPropertiesBindingPostProcessor implements BeanPostProc
|
|||
this.ownedValidator = true;
|
||||
}
|
||||
}
|
||||
if (this.conversionService == null) {
|
||||
this.conversionService = getOptionalBean(
|
||||
ConfigurableApplicationContext.CONVERSION_SERVICE_BEAN_NAME,
|
||||
ConversionService.class);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isJsr303Present() {
|
||||
|
|
@ -219,7 +233,7 @@ public class ConfigurationPropertiesBindingPostProcessor implements BeanPostProc
|
|||
|
||||
@Override
|
||||
public void destroy() throws Exception {
|
||||
if (this.ownedValidator) {
|
||||
if (this.ownedValidator && this.validator != null) {
|
||||
((DisposableBean) this.validator).destroy();
|
||||
}
|
||||
}
|
||||
|
|
@ -339,6 +353,7 @@ public class ConfigurationPropertiesBindingPostProcessor implements BeanPostProc
|
|||
}
|
||||
|
||||
private Validator determineValidator(Object bean) {
|
||||
initializeValidator();
|
||||
boolean globalValidatorSupportBean = (this.validator != null
|
||||
&& this.validator.supports(bean.getClass()));
|
||||
if (ClassUtils.isAssignable(Validator.class, bean.getClass())) {
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ import org.springframework.context.annotation.Bean;
|
|||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
|
||||
import org.springframework.mock.env.MockEnvironment;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.validation.BindException;
|
||||
import org.springframework.validation.Errors;
|
||||
import org.springframework.validation.ValidationUtils;
|
||||
|
|
@ -51,6 +52,7 @@ import static org.hamcrest.Matchers.startsWith;
|
|||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
|
@ -116,6 +118,16 @@ public class ConfigurationPropertiesBindingPostProcessorTests {
|
|||
assertBindingFailure(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidationAndNullOutValidator() {
|
||||
this.context = new AnnotationConfigApplicationContext();
|
||||
this.context.register(TestConfiguration.class);
|
||||
this.context.refresh();
|
||||
ConfigurationPropertiesBindingPostProcessor bean = this.context
|
||||
.getBean(ConfigurationPropertiesBindingPostProcessor.class);
|
||||
assertNull(ReflectionTestUtils.getField(bean, "validator"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccessfulValidationWithJSR303() {
|
||||
MockEnvironment env = new MockEnvironment();
|
||||
|
|
|
|||
Loading…
Reference in New Issue