Refine validator cleanup logic

Refine the validator memory optimization so that only directly created
validators are nulled out. Also update the logic to ensure that
`destroy` is also called.

See gh-4734
pull/4753/head
Phillip Webb 9 years ago
parent bbbe4fdcd0
commit f3bcf94fb0

@ -90,9 +90,9 @@ public class ConfigurationPropertiesBindingPostProcessor
private PropertySources propertySources;
private volatile Validator validator;
private Validator validator;
private boolean ownedValidator = false;
private volatile Validator localValidator;
private ConversionService conversionService;
@ -195,7 +195,9 @@ public class ConfigurationPropertiesBindingPostProcessor
if (this.propertySources == null) {
this.propertySources = deducePropertySources();
}
initializeValidator();
if (this.validator == null) {
this.validator = getOptionalBean(VALIDATOR_BEAN_NAME, Validator.class);
}
if (this.conversionService == null) {
this.conversionService = getOptionalBean(
ConfigurableApplicationContext.CONVERSION_SERVICE_BEAN_NAME,
@ -205,36 +207,24 @@ public class ConfigurationPropertiesBindingPostProcessor
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
if (this.ownedValidator && this.validator != null && isJsr303Present()) {
this.validator = null; // allow it to be garbage collected
}
freeLocalValidator();
}
private void initializeValidator() {
if (this.validator == null) {
this.validator = getOptionalBean(VALIDATOR_BEAN_NAME, Validator.class);
if (this.validator == null && isJsr303Present()) {
this.validator = new Jsr303ValidatorFactory()
.run(this.applicationContext);
this.ownedValidator = true;
}
}
@Override
public void destroy() throws Exception {
freeLocalValidator();
}
private boolean isJsr303Present() {
for (String validatorClass : VALIDATOR_CLASSES) {
if (!ClassUtils.isPresent(validatorClass,
this.applicationContext.getClassLoader())) {
return false;
private void freeLocalValidator() {
try {
Validator validator = this.localValidator;
this.localValidator = null;
if (validator != null) {
((DisposableBean) validator).destroy();
}
}
return true;
}
@Override
public void destroy() throws Exception {
if (this.ownedValidator && this.validator != null) {
((DisposableBean) this.validator).destroy();
catch (Exception ex) {
throw new IllegalStateException(ex);
}
}
@ -244,13 +234,11 @@ public class ConfigurationPropertiesBindingPostProcessor
// Flatten the sources into a single list so they can be iterated
return new FlatPropertySources(configurer.getAppliedPropertySources());
}
if (this.environment instanceof ConfigurableEnvironment) {
MutablePropertySources propertySources = ((ConfigurableEnvironment) this.environment)
.getPropertySources();
return new FlatPropertySources(propertySources);
}
// empty, so not very useful, but fulfils the contract
return new MutablePropertySources();
}
@ -353,16 +341,36 @@ public class ConfigurationPropertiesBindingPostProcessor
}
private Validator determineValidator(Object bean) {
initializeValidator();
boolean globalValidatorSupportBean = (this.validator != null
&& this.validator.supports(bean.getClass()));
Validator validator = getValidator();
boolean supportsBean = (validator != null && validator.supports(bean.getClass()));
if (ClassUtils.isAssignable(Validator.class, bean.getClass())) {
if (!globalValidatorSupportBean) {
return (Validator) bean;
if (supportsBean) {
return new ChainingValidator(validator, (Validator) bean);
}
return new ChainingValidator(this.validator, (Validator) bean);
return (Validator) bean;
}
return (globalValidatorSupportBean ? this.validator : null);
return (supportsBean ? validator : null);
}
private Validator getValidator() {
if (this.validator != null) {
return this.validator;
}
if (this.localValidator == null && isJsr303Present()) {
this.localValidator = new LocalValidatorFactory()
.run(this.applicationContext);
}
return this.localValidator;
}
private boolean isJsr303Present() {
for (String validatorClass : VALIDATOR_CLASSES) {
if (!ClassUtils.isPresent(validatorClass,
this.applicationContext.getClassLoader())) {
return false;
}
}
return true;
}
private PropertySources loadPropertySources(String[] locations,
@ -408,7 +416,7 @@ public class ConfigurationPropertiesBindingPostProcessor
* Factory to create JSR 303 LocalValidatorFactoryBean. Inner class to prevent class
* loader issues.
*/
private static class Jsr303ValidatorFactory {
private static class LocalValidatorFactory {
public Validator run(ApplicationContext applicationContext) {
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();

Loading…
Cancel
Save