Turn (Jackson|Gson)AutoConfiguration into true auto-configuration

Previously JacksonAutoConfiguration and GsonAutoConfiguration were
not actually auto-configuration classes. They were only processed
due to being imported by HttpMessageConvertersAutoConfiguration.
In addition to being misleadingly named, this meant that they could
not be included or excluded individually and were also tightly coupled
to HTTP message conversion.

This commit updates spring.factories to make both
JacksonAutoConfiguration and GsonAutoConfiguration actual
auto-configuration classes. As a result, they can now be enabled or
disabled individually and are no longer coupled to HTTP message
conversion.

Closes gh-1562
This commit is contained in:
Andy Wilkinson
2014-10-02 10:27:21 +01:00
parent 02e33c125c
commit de8a2a71d0
3 changed files with 99 additions and 38 deletions

View File

@@ -21,14 +21,12 @@ import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration;
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.GsonHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
@@ -44,10 +42,10 @@ import com.google.gson.Gson;
* @author Piotr Maj
* @author Oliver Gierke
* @author David Liu
* @author Andy Wilkinson
*/
@Configuration
@ConditionalOnClass(HttpMessageConverter.class)
@Import({ JacksonAutoConfiguration.class, GsonAutoConfiguration.class })
public class HttpMessageConvertersAutoConfiguration {
@Autowired(required = false)
@@ -61,8 +59,9 @@ public class HttpMessageConvertersAutoConfiguration {
@Configuration
@ConditionalOnClass(ObjectMapper.class)
@ConditionalOnBean(ObjectMapper.class)
@EnableConfigurationProperties(HttpMapperProperties.class)
protected static class ObjectMappers {
protected static class MappingJackson2HttpMessageConverterConfiguration {
@Autowired
private HttpMapperProperties properties = new HttpMapperProperties();
@@ -81,7 +80,8 @@ public class HttpMessageConvertersAutoConfiguration {
@Configuration
@ConditionalOnClass(Gson.class)
protected static class GsonConfiguration {
@ConditionalOnBean(Gson.class)
protected static class GsonHttpMessageConverterConfiguration {
@Bean
@ConditionalOnMissingBean

View File

@@ -16,8 +16,10 @@ org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfigura
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\

View File

@@ -16,6 +16,9 @@
package org.springframework.boot.autoconfigure.web;
import java.util.Arrays;
import java.util.List;
import org.junit.After;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
@@ -36,6 +39,7 @@ import static org.junit.Assert.assertTrue;
* @author Dave Syer
* @author Oliver Gierke
* @author David Liu
* @author Andy Wilkinson
*/
public class HttpMessageConvertersAutoConfigurationTests {
@@ -49,14 +53,75 @@ public class HttpMessageConvertersAutoConfigurationTests {
}
@Test
public void customJacksonConverter() throws Exception {
public void noObjectMapperMeansNoConverter() throws Exception {
this.context.register(HttpMessageConvertersAutoConfiguration.class);
this.context.refresh();
assertTrue(this.context.getBeansOfType(ObjectMapper.class).isEmpty());
assertTrue(this.context.getBeansOfType(MappingJackson2HttpMessageConverter.class)
.isEmpty());
}
@Test
public void defaultJacksonConverter() throws Exception {
this.context.register(JacksonConfig.class,
HttpMessageConvertersAutoConfiguration.class);
this.context.refresh();
MappingJackson2HttpMessageConverter converter = this.context
.getBean(MappingJackson2HttpMessageConverter.class);
assertEquals(this.context.getBean(ObjectMapper.class),
converter.getObjectMapper());
assertConverterBeanExists(MappingJackson2HttpMessageConverter.class,
"mappingJackson2HttpMessageConverter");
assertConverterBeanRegisteredWithHttpMessageConverters(MappingJackson2HttpMessageConverter.class);
}
@Test
public void customJacksonConverter() throws Exception {
this.context.register(JacksonConfig.class, JacksonConverterConfig.class,
HttpMessageConvertersAutoConfiguration.class);
this.context.refresh();
assertConverterBeanExists(MappingJackson2HttpMessageConverter.class,
"customJacksonMessageConverter");
}
@Test
public void noGson() throws Exception {
this.context.register(HttpMessageConvertersAutoConfiguration.class);
this.context.refresh();
assertTrue(this.context.getBeansOfType(Gson.class).isEmpty());
assertTrue(this.context.getBeansOfType(GsonHttpMessageConverter.class).isEmpty());
}
@Test
public void defaultGsonConverter() throws Exception {
this.context.register(GsonConfig.class,
HttpMessageConvertersAutoConfiguration.class);
this.context.refresh();
assertConverterBeanExists(GsonHttpMessageConverter.class,
"gsonHttpMessageConverter");
assertConverterBeanRegisteredWithHttpMessageConverters(GsonHttpMessageConverter.class);
}
@Test
public void customGsonConverter() throws Exception {
this.context.register(GsonConfig.class, GsonConverterConfig.class,
HttpMessageConvertersAutoConfiguration.class);
this.context.refresh();
assertConverterBeanExists(GsonHttpMessageConverter.class,
"customGsonMessageConverter");
assertConverterBeanRegisteredWithHttpMessageConverters(GsonHttpMessageConverter.class);
}
private void assertConverterBeanExists(Class<?> type, String beanName) {
assertEquals(1, this.context.getBeansOfType(type).size());
List<String> beanNames = Arrays.asList(this.context.getBeanDefinitionNames());
assertTrue(beanName + " not found in " + beanNames, beanNames.contains(beanName));
}
private void assertConverterBeanRegisteredWithHttpMessageConverters(Class<?> type) {
Object converter = this.context.getBean(type);
HttpMessageConverters converters = this.context
.getBean(HttpMessageConverters.class);
assertTrue(converters.getConverters().contains(converter));
@@ -64,48 +129,42 @@ public class HttpMessageConvertersAutoConfigurationTests {
@Configuration
protected static class JacksonConfig {
@Bean
public MappingJackson2HttpMessageConverter jacksonMessageConverter() {
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setObjectMapper(objectMapper());
return converter;
}
@Bean
public ObjectMapper objectMapper() {
return new ObjectMapper();
}
}
@Test
public void customGsonConverter() throws Exception {
this.context.register(GsonConfig.class,
HttpMessageConvertersAutoConfiguration.class);
this.context.refresh();
GsonHttpMessageConverter converter = this.context
.getBean(GsonHttpMessageConverter.class);
assertEquals(this.context.getBean(Gson.class), converter.getGson());
HttpMessageConverters converters = this.context
.getBean(HttpMessageConverters.class);
assertTrue(converters.getConverters().contains(converter));
@Configuration
protected static class JacksonConverterConfig {
@Bean
public MappingJackson2HttpMessageConverter customJacksonMessageConverter(
ObjectMapper objectMapper) {
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setObjectMapper(objectMapper);
return converter;
}
}
@Configuration
protected static class GsonConfig {
@Bean
public GsonHttpMessageConverter gsonMessageConverter() {
GsonHttpMessageConverter converter = new GsonHttpMessageConverter();
converter.setGson(gson());
return converter;
}
@Bean
public Gson gson() {
return new Gson();
}
}
@Configuration
protected static class GsonConverterConfig {
@Bean
public GsonHttpMessageConverter customGsonMessageConverter(Gson gson) {
GsonHttpMessageConverter converter = new GsonHttpMessageConverter();
converter.setGson(gson);
return converter;
}
}
}