Remove tangles from core + minor polish

pull/7/head
Phillip Webb 12 years ago
parent 2c05e9f150
commit b838dc5422

@ -43,7 +43,7 @@ import org.springframework.zero.context.annotation.EnableAutoConfiguration;
import org.springframework.zero.context.condition.ConditionalOnClass; import org.springframework.zero.context.condition.ConditionalOnClass;
import org.springframework.zero.context.condition.ConditionalOnMissingBean; import org.springframework.zero.context.condition.ConditionalOnMissingBean;
import org.springframework.zero.context.embedded.AnnotationConfigEmbeddedWebApplicationContext; import org.springframework.zero.context.embedded.AnnotationConfigEmbeddedWebApplicationContext;
import org.springframework.zero.context.embedded.ServerProperties; import org.springframework.zero.context.embedded.properties.ServerProperties;
/** /**
* {@link EnableAutoConfiguration Auto-configuration} to enable Spring MVC to handle * {@link EnableAutoConfiguration Auto-configuration} to enable Spring MVC to handle

@ -20,7 +20,7 @@ import java.net.InetAddress;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import org.springframework.zero.context.embedded.ServerProperties; import org.springframework.zero.context.embedded.properties.ServerProperties;
import org.springframework.zero.context.properties.ConfigurationProperties; import org.springframework.zero.context.properties.ConfigurationProperties;
/** /**

@ -27,7 +27,7 @@ import org.springframework.zero.context.annotation.EnableAutoConfiguration;
import org.springframework.zero.context.condition.ConditionalOnMissingBean; import org.springframework.zero.context.condition.ConditionalOnMissingBean;
import org.springframework.zero.context.embedded.ConfigurableEmbeddedServletContainerFactory; import org.springframework.zero.context.embedded.ConfigurableEmbeddedServletContainerFactory;
import org.springframework.zero.context.embedded.EmbeddedServletContainerCustomizer; import org.springframework.zero.context.embedded.EmbeddedServletContainerCustomizer;
import org.springframework.zero.context.embedded.ServerProperties; import org.springframework.zero.context.embedded.properties.ServerProperties;
import org.springframework.zero.context.properties.EnableConfigurationProperties; import org.springframework.zero.context.properties.EnableConfigurationProperties;
/** /**

@ -33,7 +33,7 @@ import org.springframework.zero.context.embedded.AnnotationConfigEmbeddedWebAppl
import org.springframework.zero.context.embedded.ConfigurableEmbeddedServletContainerFactory; import org.springframework.zero.context.embedded.ConfigurableEmbeddedServletContainerFactory;
import org.springframework.zero.context.embedded.EmbeddedServletContainerCustomizerBeanPostProcessor; import org.springframework.zero.context.embedded.EmbeddedServletContainerCustomizerBeanPostProcessor;
import org.springframework.zero.context.embedded.EmbeddedServletContainerFactory; import org.springframework.zero.context.embedded.EmbeddedServletContainerFactory;
import org.springframework.zero.context.embedded.ServerProperties; import org.springframework.zero.context.embedded.properties.ServerProperties;
import org.springframework.zero.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory; import org.springframework.zero.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;

@ -59,13 +59,13 @@ public class PropertiesConfigurationFactory<T> implements FactoryBean<T>,
private PropertySources propertySources; private PropertySources propertySources;
private T configuration; private T target;
private Validator validator; private Validator validator;
private MessageSource messageSource; private MessageSource messageSource;
private boolean initialized = false; private boolean hasBeenBound = false;
private String targetName; private String targetName;
@ -77,7 +77,7 @@ public class PropertiesConfigurationFactory<T> implements FactoryBean<T>,
*/ */
public PropertiesConfigurationFactory(T target) { public PropertiesConfigurationFactory(T target) {
Assert.notNull(target); Assert.notNull(target);
this.configuration = target; this.target = target;
} }
/** /**
@ -88,7 +88,7 @@ public class PropertiesConfigurationFactory<T> implements FactoryBean<T>,
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public PropertiesConfigurationFactory(Class<?> type) { public PropertiesConfigurationFactory(Class<?> type) {
Assert.notNull(type); Assert.notNull(type);
this.configuration = (T) BeanUtils.instantiate(type); this.target = (T) BeanUtils.instantiate(type);
} }
/** /**
@ -165,99 +165,98 @@ public class PropertiesConfigurationFactory<T> implements FactoryBean<T>,
@Override @Override
public void afterPropertiesSet() throws Exception { public void afterPropertiesSet() throws Exception {
bindPropertiesToTarget();
}
@Override
public Class<?> getObjectType() {
if (this.target == null) {
return Object.class;
}
return this.target.getClass();
}
@Override
public boolean isSingleton() {
return true;
}
@Override
public T getObject() throws Exception {
if (!this.hasBeenBound) {
bindPropertiesToTarget();
}
return this.target;
}
public void bindPropertiesToTarget() throws BindException {
Assert.state(this.properties != null || this.propertySources != null, Assert.state(this.properties != null || this.propertySources != null,
"Properties or propertySources should not be null"); "Properties or propertySources should not be null");
try { try {
if (this.properties != null) { if (logger.isTraceEnabled()) {
logger.trace("Properties:\n" + this.properties); if (this.properties != null) {
} logger.trace("Properties:\n" + this.properties);
else { }
logger.trace("Property Sources: " + this.propertySources); else {
} logger.trace("Property Sources: " + this.propertySources);
this.initialized = true;
RelaxedDataBinder dataBinder;
if (this.targetName != null) {
dataBinder = new RelaxedDataBinder(this.configuration, this.targetName);
}
else {
dataBinder = new RelaxedDataBinder(this.configuration);
}
if (this.validator != null) {
dataBinder.setValidator(this.validator);
}
if (this.conversionService != null) {
dataBinder.setConversionService(this.conversionService);
}
dataBinder.setIgnoreInvalidFields(this.ignoreInvalidFields);
dataBinder.setIgnoreUnknownFields(this.ignoreUnknownFields);
customizeBinder(dataBinder);
PropertyValues pvs;
if (this.properties != null) {
pvs = new MutablePropertyValues(this.properties);
}
else {
pvs = new PropertySourcesPropertyValues(this.propertySources);
}
dataBinder.bind(pvs);
if (this.validator != null) {
dataBinder.validate();
BindingResult errors = dataBinder.getBindingResult();
if (errors.hasErrors()) {
logger.error("Properties configuration failed validation");
for (ObjectError error : errors.getAllErrors()) {
logger.error(this.messageSource != null ? this.messageSource
.getMessage(error, Locale.getDefault())
+ " ("
+ error
+ ")" : error);
}
if (this.exceptionIfInvalid) {
BindException summary = new BindException(errors);
throw summary;
}
} }
} }
this.hasBeenBound = true;
doBindPropertiesToTarget();
} }
catch (BindException e) { catch (BindException e) {
if (this.exceptionIfInvalid) { if (this.exceptionIfInvalid) {
throw e; throw e;
} }
logger.error( logger.error("Failed to load Properties validation bean. "
"Failed to load Properties validation bean. Your Properties may be invalid.", + "Your Properties may be invalid.", e);
e);
} }
} }
/** private void doBindPropertiesToTarget() throws BindException {
* @param dataBinder the data binder that will be used to bind and validate
*/
protected void customizeBinder(DataBinder dataBinder) {
}
@Override RelaxedDataBinder dataBinder = (this.targetName != null ? new RelaxedDataBinder(
public Class<?> getObjectType() { this.target, this.targetName) : new RelaxedDataBinder(this.target));
if (this.configuration == null) { if (this.validator != null) {
return Object.class; dataBinder.setValidator(this.validator);
} }
return this.configuration.getClass(); if (this.conversionService != null) {
} dataBinder.setConversionService(this.conversionService);
}
dataBinder.setIgnoreInvalidFields(this.ignoreInvalidFields);
dataBinder.setIgnoreUnknownFields(this.ignoreUnknownFields);
customizeBinder(dataBinder);
@Override PropertyValues propertyValues = (this.properties != null ? new MutablePropertyValues(
public boolean isSingleton() { this.properties)
return true; : new PropertySourcesPropertyValues(this.propertySources));
dataBinder.bind(propertyValues);
if (this.validator != null) {
validate(dataBinder);
}
} }
@Override private void validate(RelaxedDataBinder dataBinder) throws BindException {
public T getObject() throws Exception { dataBinder.validate();
if (!this.initialized) { BindingResult errors = dataBinder.getBindingResult();
afterPropertiesSet(); if (errors.hasErrors()) {
logger.error("Properties configuration failed validation");
for (ObjectError error : errors.getAllErrors()) {
logger.error(this.messageSource != null ? this.messageSource.getMessage(
error, Locale.getDefault()) + " (" + error + ")" : error);
}
if (this.exceptionIfInvalid) {
BindException summary = new BindException(errors);
throw summary;
}
} }
return this.configuration; }
/**
* @param dataBinder the data binder that will be used to bind and validate
*/
protected void customizeBinder(DataBinder dataBinder) {
} }
} }

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.zero.context.embedded; package org.springframework.zero.context.embedded.properties;
import java.io.File; import java.io.File;
import java.net.InetAddress; import java.net.InetAddress;
@ -24,6 +24,10 @@ import javax.validation.constraints.NotNull;
import org.apache.catalina.valves.AccessLogValve; import org.apache.catalina.valves.AccessLogValve;
import org.apache.catalina.valves.RemoteIpValve; import org.apache.catalina.valves.RemoteIpValve;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.zero.context.embedded.ConfigurableEmbeddedServletContainerFactory;
import org.springframework.zero.context.embedded.EmbeddedServletContainerCustomizer;
import org.springframework.zero.context.embedded.EmbeddedServletContainerCustomizerBeanPostProcessor;
import org.springframework.zero.context.embedded.EmbeddedServletContainerFactory;
import org.springframework.zero.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory; import org.springframework.zero.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.zero.context.properties.ConfigurationProperties; import org.springframework.zero.context.properties.ConfigurationProperties;

@ -27,9 +27,9 @@ import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.converter.Converter; import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.core.env.PropertySources; import org.springframework.core.env.PropertySources;
import org.springframework.util.StringUtils;
import org.springframework.validation.Validator; import org.springframework.validation.Validator;
import org.springframework.zero.bind.PropertiesConfigurationFactory; import org.springframework.zero.bind.PropertiesConfigurationFactory;
import org.springframework.zero.context.properties.EnableConfigurationPropertiesImportSelector.ConfigurationPropertiesHolder;
/** /**
* {@link BeanPostProcessor} to bind {@link PropertySources} to beans annotated with * {@link BeanPostProcessor} to bind {@link PropertySources} to beans annotated with
@ -89,44 +89,41 @@ public class ConfigurationPropertiesBindingPostProcessor implements BeanPostProc
throws BeansException { throws BeansException {
ConfigurationProperties annotation = AnnotationUtils.findAnnotation( ConfigurationProperties annotation = AnnotationUtils.findAnnotation(
bean.getClass(), ConfigurationProperties.class); bean.getClass(), ConfigurationProperties.class);
Object target = bean;
if (annotation != null || bean instanceof ConfigurationPropertiesHolder) { if (annotation != null || bean instanceof ConfigurationPropertiesHolder) {
if (bean instanceof ConfigurationPropertiesHolder) { postProcessAfterInitialization(bean, beanName, annotation);
target = ((ConfigurationPropertiesHolder) bean).getTarget();
}
PropertiesConfigurationFactory<Object> factory = new PropertiesConfigurationFactory<Object>(
target);
factory.setPropertySources(this.propertySources);
factory.setValidator(this.validator);
// If no explicit conversion service is provided we add one so that (at least)
// comma-separated arrays of convertibles can be bound automatically
factory.setConversionService(this.conversionService == null ? getDefaultConversionService()
: this.conversionService);
String targetName = null;
if (annotation != null) {
factory.setIgnoreInvalidFields(annotation.ignoreInvalidFields());
factory.setIgnoreUnknownFields(annotation.ignoreUnknownFields());
targetName = "".equals(annotation.value()) ? (""
.equals(annotation.name()) ? null : annotation.name())
: annotation.value();
}
factory.setTargetName(targetName);
try {
target = factory.getObject(); // throwaway
}
catch (BeansException e) {
throw e;
}
catch (Exception e) {
throw new BeanCreationException(beanName, "Could not bind", e);
}
} }
return bean; return bean;
} }
/** private void postProcessAfterInitialization(Object bean, String beanName,
* @return ConfigurationProperties annotation) {
*/ Object target = (bean instanceof ConfigurationPropertiesHolder ? ((ConfigurationPropertiesHolder) bean)
.getTarget() : bean);
PropertiesConfigurationFactory<Object> factory = new PropertiesConfigurationFactory<Object>(
target);
factory.setPropertySources(this.propertySources);
factory.setValidator(this.validator);
// If no explicit conversion service is provided we add one so that (at least)
// comma-separated arrays of convertibles can be bound automatically
factory.setConversionService(this.conversionService == null ? getDefaultConversionService()
: this.conversionService);
if (annotation != null) {
factory.setIgnoreInvalidFields(annotation.ignoreInvalidFields());
factory.setIgnoreUnknownFields(annotation.ignoreUnknownFields());
String targetName = (StringUtils.hasLength(annotation.value()) ? annotation
.value() : annotation.name());
if (StringUtils.hasLength(targetName)) {
factory.setTargetName(targetName);
}
}
try {
factory.bindPropertiesToTarget();
}
catch (Exception ex) {
throw new BeanCreationException(beanName, "Could not bind properties", ex);
}
}
private ConversionService getDefaultConversionService() { private ConversionService getDefaultConversionService() {
if (!this.initialized && this.beanFactory instanceof ListableBeanFactory) { if (!this.initialized && this.beanFactory instanceof ListableBeanFactory) {
for (Converter<?, ?> converter : ((ListableBeanFactory) this.beanFactory) for (Converter<?, ?> converter : ((ListableBeanFactory) this.beanFactory)

@ -0,0 +1,37 @@
/*
* Copyright 2012-2013 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.zero.context.properties;
/**
* Properties holder registered by {@link EnableConfigurationPropertiesImportSelector} to
* be picked up by {@link ConfigurationPropertiesBindingPostProcessor}.
*
* @author Dave Syer
*/
class ConfigurationPropertiesHolder {
private Object target;
public ConfigurationPropertiesHolder(Object target) {
this.target = target;
}
public Object getTarget() {
return this.target;
}
}

@ -19,6 +19,7 @@ package org.springframework.zero.context.properties;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
@ -67,17 +68,7 @@ class EnableConfigurationPropertiesImportSelector implements ImportSelector {
for (Class<?> type : types) { for (Class<?> type : types) {
String name = type.getName(); String name = type.getName();
if (!registry.containsBeanDefinition(name)) { if (!registry.containsBeanDefinition(name)) {
registry.registerBeanDefinition(name, BeanDefinitionBuilder registerBeanDefinition(registry, type, name);
.genericBeanDefinition(type).getBeanDefinition());
ConfigurationProperties properties = AnnotationUtils.findAnnotation(
type, ConfigurationProperties.class);
if (properties == null) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder
.genericBeanDefinition(ConfigurationPropertiesHolder.class);
builder.addConstructorArgReference(name);
registry.registerBeanDefinition(name + ".HOLDER",
builder.getBeanDefinition());
}
} }
} }
} }
@ -94,18 +85,25 @@ class EnableConfigurationPropertiesImportSelector implements ImportSelector {
return result; return result;
} }
} private void registerBeanDefinition(BeanDefinitionRegistry registry,
Class<?> type, String name) {
public static class ConfigurationPropertiesHolder { BeanDefinitionBuilder builder = BeanDefinitionBuilder
.genericBeanDefinition(type);
AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
registry.registerBeanDefinition(name, beanDefinition);
private Object target; ConfigurationProperties properties = AnnotationUtils.findAnnotation(type,
ConfigurationProperties.class);
public ConfigurationPropertiesHolder(Object target) { if (properties == null) {
this.target = target; registerPropertiesHolder(registry, name);
}
} }
public Object getTarget() { private void registerPropertiesHolder(BeanDefinitionRegistry registry, String name) {
return this.target; BeanDefinitionBuilder builder = BeanDefinitionBuilder
.genericBeanDefinition(ConfigurationPropertiesHolder.class);
builder.addConstructorArgReference(name);
registry.registerBeanDefinition(name + ".HOLDER", builder.getBeanDefinition());
} }
} }

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.zero.context.embedded; package org.springframework.zero.context.embedded.properties;
import java.net.InetAddress; import java.net.InetAddress;
import java.util.Collections; import java.util.Collections;
@ -24,6 +24,7 @@ import java.util.Map;
import org.junit.Test; import org.junit.Test;
import org.springframework.beans.MutablePropertyValues; import org.springframework.beans.MutablePropertyValues;
import org.springframework.zero.bind.RelaxedDataBinder; import org.springframework.zero.bind.RelaxedDataBinder;
import org.springframework.zero.context.embedded.properties.ServerProperties;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
Loading…
Cancel
Save