Skip to content

Commit 9db2031

Browse files
committed
Polish "Add Printer and Parser beans to conversion service"
Extract common registration code and make use of the Spring Framework registration methods. See gh-17064
1 parent 955eaa8 commit 9db2031

File tree

10 files changed

+249
-510
lines changed

10 files changed

+249
-510
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfiguration.java

+2-33
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
package org.springframework.boot.autoconfigure.web.reactive;
1818

1919
import java.time.Duration;
20-
import java.util.Collection;
2120

2221
import org.apache.commons.logging.Log;
2322
import org.apache.commons.logging.LogFactory;
@@ -38,20 +37,14 @@
3837
import org.springframework.boot.autoconfigure.web.ResourceProperties;
3938
import org.springframework.boot.autoconfigure.web.format.WebConversionService;
4039
import org.springframework.boot.context.properties.EnableConfigurationProperties;
41-
import org.springframework.boot.convert.ParserConverter;
42-
import org.springframework.boot.convert.PrinterConverter;
40+
import org.springframework.boot.convert.ApplicationConversionService;
4341
import org.springframework.boot.web.codec.CodecCustomizer;
4442
import org.springframework.boot.web.reactive.filter.OrderedHiddenHttpMethodFilter;
4543
import org.springframework.context.annotation.Bean;
4644
import org.springframework.context.annotation.Configuration;
4745
import org.springframework.context.annotation.Import;
4846
import org.springframework.core.Ordered;
49-
import org.springframework.core.convert.converter.Converter;
50-
import org.springframework.core.convert.converter.GenericConverter;
51-
import org.springframework.format.Formatter;
5247
import org.springframework.format.FormatterRegistry;
53-
import org.springframework.format.Parser;
54-
import org.springframework.format.Printer;
5548
import org.springframework.format.support.FormattingConversionService;
5649
import org.springframework.http.codec.ServerCodecConfigurer;
5750
import org.springframework.util.ClassUtils;
@@ -180,37 +173,13 @@ public void configureViewResolvers(ViewResolverRegistry registry) {
180173

181174
@Override
182175
public void addFormatters(FormatterRegistry registry) {
183-
for (Converter<?, ?> converter : getBeansOfType(Converter.class)) {
184-
registry.addConverter(converter);
185-
}
186-
for (GenericConverter converter : getBeansOfType(GenericConverter.class)) {
187-
registry.addConverter(converter);
188-
}
189-
for (Formatter<?> formatter : getBeansOfType(Formatter.class)) {
190-
registry.addFormatter(formatter);
191-
}
192-
for (Printer<?> printer : getBeansOfType(Printer.class)) {
193-
if (!(printer instanceof Formatter<?>)) {
194-
registry.addConverter(new PrinterConverter(printer));
195-
196-
}
197-
}
198-
for (Parser<?> parser : getBeansOfType(Parser.class)) {
199-
if (!(parser instanceof Formatter<?>)) {
200-
registry.addConverter(new ParserConverter(parser));
201-
}
202-
}
203-
}
204-
205-
private <T> Collection<T> getBeansOfType(Class<T> type) {
206-
return this.beanFactory.getBeansOfType(type).values();
176+
ApplicationConversionService.addBeans(registry, this.beanFactory);
207177
}
208178

209179
private void customizeResourceHandlerRegistration(ResourceHandlerRegistration registration) {
210180
if (this.resourceHandlerRegistrationCustomizer != null) {
211181
this.resourceHandlerRegistrationCustomizer.customize(registration);
212182
}
213-
214183
}
215184

216185
}

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.java

+2-31
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import java.time.Duration;
2020
import java.util.ArrayList;
2121
import java.util.Arrays;
22-
import java.util.Collection;
2322
import java.util.Collections;
2423
import java.util.List;
2524
import java.util.ListIterator;
@@ -55,8 +54,7 @@
5554
import org.springframework.boot.autoconfigure.web.ResourceProperties.Strategy;
5655
import org.springframework.boot.autoconfigure.web.format.WebConversionService;
5756
import org.springframework.boot.context.properties.EnableConfigurationProperties;
58-
import org.springframework.boot.convert.ParserConverter;
59-
import org.springframework.boot.convert.PrinterConverter;
57+
import org.springframework.boot.convert.ApplicationConversionService;
6058
import org.springframework.boot.web.servlet.filter.OrderedFormContentFilter;
6159
import org.springframework.boot.web.servlet.filter.OrderedHiddenHttpMethodFilter;
6260
import org.springframework.boot.web.servlet.filter.OrderedRequestContextFilter;
@@ -68,16 +66,11 @@
6866
import org.springframework.context.annotation.Primary;
6967
import org.springframework.core.Ordered;
7068
import org.springframework.core.annotation.Order;
71-
import org.springframework.core.convert.converter.Converter;
72-
import org.springframework.core.convert.converter.GenericConverter;
7369
import org.springframework.core.io.ClassPathResource;
7470
import org.springframework.core.io.Resource;
7571
import org.springframework.core.io.ResourceLoader;
7672
import org.springframework.core.task.AsyncTaskExecutor;
77-
import org.springframework.format.Formatter;
7873
import org.springframework.format.FormatterRegistry;
79-
import org.springframework.format.Parser;
80-
import org.springframework.format.Printer;
8174
import org.springframework.format.support.FormattingConversionService;
8275
import org.springframework.http.CacheControl;
8376
import org.springframework.http.MediaType;
@@ -302,29 +295,7 @@ public MessageCodesResolver getMessageCodesResolver() {
302295

303296
@Override
304297
public void addFormatters(FormatterRegistry registry) {
305-
for (Converter<?, ?> converter : getBeansOfType(Converter.class)) {
306-
registry.addConverter(converter);
307-
}
308-
for (GenericConverter converter : getBeansOfType(GenericConverter.class)) {
309-
registry.addConverter(converter);
310-
}
311-
for (Formatter<?> formatter : getBeansOfType(Formatter.class)) {
312-
registry.addFormatter(formatter);
313-
}
314-
for (Printer<?> printer : getBeansOfType(Printer.class)) {
315-
if (!(printer instanceof Formatter<?>)) {
316-
registry.addConverter(new PrinterConverter(printer));
317-
}
318-
}
319-
for (Parser<?> parser : getBeansOfType(Parser.class)) {
320-
if (!(parser instanceof Formatter<?>)) {
321-
registry.addConverter(new ParserConverter(parser));
322-
}
323-
}
324-
}
325-
326-
private <T> Collection<T> getBeansOfType(Class<T> type) {
327-
return this.beanFactory.getBeansOfType(type).values();
298+
ApplicationConversionService.addBeans(registry, this.beanFactory);
328299
}
329300

330301
@Override

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfigurationTests.java

+27-29
Original file line numberDiff line numberDiff line change
@@ -381,10 +381,9 @@ void cacheControl() {
381381
void customPrinterAndParserShouldBeRegisteredAsConverters() {
382382
this.contextRunner.withUserConfiguration(ParserConfiguration.class, PrinterConfiguration.class)
383383
.run((context) -> {
384-
Foo foo = new Foo("bar");
385-
ConversionService conversionService = context.getBean(ConversionService.class);
386-
assertThat(conversionService.convert(foo, String.class)).isEqualTo("bar");
387-
assertThat(conversionService.convert("bar", Foo.class)).extracting(Foo::toString).isEqualTo("bar");
384+
ConversionService service = context.getBean(ConversionService.class);
385+
assertThat(service.convert(new Example("spring", new Date()), String.class)).isEqualTo("spring");
386+
assertThat(service.convert("boot", Example.class)).extracting(Example::getName).isEqualTo("boot");
388387
});
389388
}
390389

@@ -564,17 +563,8 @@ private static class MyRequestMappingHandlerMapping extends RequestMappingHandle
564563
static class PrinterConfiguration {
565564

566565
@Bean
567-
public Printer<Foo> fooPrinter() {
568-
return new FooPrinter();
569-
}
570-
571-
private static class FooPrinter implements Printer<Foo> {
572-
573-
@Override
574-
public String print(Foo foo, Locale locale) {
575-
return foo.toString();
576-
}
577-
566+
public Printer<Example> examplePrinter() {
567+
return new ExamplePrinter();
578568
}
579569

580570
}
@@ -583,32 +573,40 @@ public String print(Foo foo, Locale locale) {
583573
static class ParserConfiguration {
584574

585575
@Bean
586-
public Parser<Foo> fooParser() {
587-
return new FooParser();
576+
public Parser<Example> exampleParser() {
577+
return new ExampleParser();
588578
}
589579

590-
private static class FooParser implements Parser<Foo> {
580+
}
591581

592-
@Override
593-
public Foo parse(String source, Locale locale) {
594-
return new Foo(source);
595-
}
582+
static final class Example {
583+
584+
private final String name;
596585

586+
private Example(String name, Date date) {
587+
this.name = name;
597588
}
598589

599-
}
590+
public String getName() {
591+
return this.name;
592+
}
600593

601-
static class Foo {
594+
}
602595

603-
private final String name;
596+
private static class ExamplePrinter implements Printer<Example> {
604597

605-
Foo(String name) {
606-
this.name = name;
598+
@Override
599+
public String print(Example example, Locale locale) {
600+
return example.getName();
607601
}
608602

603+
}
604+
605+
private static class ExampleParser implements Parser<Example> {
606+
609607
@Override
610-
public String toString() {
611-
return this.name;
608+
public Example parse(String source, Locale locale) {
609+
return new Example(source, new Date());
612610
}
613611

614612
}

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfigurationTests.java

+27-29
Original file line numberDiff line numberDiff line change
@@ -779,10 +779,9 @@ void whenUserDefinesARequestContextFilterRegistrationTheAutoConfiguredFilterBack
779779
void customPrinterAndParserShouldBeRegisteredAsConverters() {
780780
this.contextRunner.withUserConfiguration(ParserConfiguration.class, PrinterConfiguration.class)
781781
.run((context) -> {
782-
Foo foo = new Foo("bar");
783-
ConversionService conversionService = context.getBean(ConversionService.class);
784-
assertThat(conversionService.convert(foo, String.class)).isEqualTo("bar");
785-
assertThat(conversionService.convert("bar", Foo.class)).extracting(Foo::toString).isEqualTo("bar");
782+
ConversionService service = context.getBean(ConversionService.class);
783+
assertThat(service.convert(new Example("spring", new Date()), String.class)).isEqualTo("spring");
784+
assertThat(service.convert("boot", Example.class)).extracting(Example::getName).isEqualTo("boot");
786785
});
787786
}
788787

@@ -1110,17 +1109,8 @@ public FilterRegistrationBean<RequestContextFilter> customRequestContextFilterRe
11101109
static class PrinterConfiguration {
11111110

11121111
@Bean
1113-
public Printer<Foo> fooPrinter() {
1114-
return new FooPrinter();
1115-
}
1116-
1117-
private static class FooPrinter implements Printer<Foo> {
1118-
1119-
@Override
1120-
public String print(Foo foo, Locale locale) {
1121-
return foo.toString();
1122-
}
1123-
1112+
public Printer<Example> examplePrinter() {
1113+
return new ExamplePrinter();
11241114
}
11251115

11261116
}
@@ -1129,32 +1119,40 @@ public String print(Foo foo, Locale locale) {
11291119
static class ParserConfiguration {
11301120

11311121
@Bean
1132-
public Parser<Foo> fooParser() {
1133-
return new FooParser();
1122+
public Parser<Example> exampleParser() {
1123+
return new ExampleParser();
11341124
}
11351125

1136-
private static class FooParser implements Parser<Foo> {
1126+
}
11371127

1138-
@Override
1139-
public Foo parse(String source, Locale locale) {
1140-
return new Foo(source);
1141-
}
1128+
static final class Example {
1129+
1130+
private final String name;
11421131

1132+
private Example(String name, Date date) {
1133+
this.name = name;
11431134
}
11441135

1145-
}
1136+
public String getName() {
1137+
return this.name;
1138+
}
11461139

1147-
static class Foo {
1140+
}
11481141

1149-
private final String name;
1142+
private static class ExamplePrinter implements Printer<Example> {
11501143

1151-
Foo(String name) {
1152-
this.name = name;
1144+
@Override
1145+
public String print(Example example, Locale locale) {
1146+
return example.getName();
11531147
}
11541148

1149+
}
1150+
1151+
private static class ExampleParser implements Parser<Example> {
1152+
11551153
@Override
1156-
public String toString() {
1157-
return this.name;
1154+
public Example parse(String source, Locale locale) {
1155+
return new Example(source, new Date());
11581156
}
11591157

11601158
}

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/convert/ApplicationConversionService.java

+42-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2018 the original author or authors.
2+
* Copyright 2012-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,11 +16,20 @@
1616

1717
package org.springframework.boot.convert;
1818

19+
import java.util.LinkedHashSet;
20+
import java.util.Set;
21+
22+
import org.springframework.beans.factory.ListableBeanFactory;
1923
import org.springframework.core.convert.ConversionService;
24+
import org.springframework.core.convert.converter.Converter;
2025
import org.springframework.core.convert.converter.ConverterRegistry;
26+
import org.springframework.core.convert.converter.GenericConverter;
2127
import org.springframework.core.convert.support.ConfigurableConversionService;
2228
import org.springframework.core.convert.support.DefaultConversionService;
29+
import org.springframework.format.Formatter;
2330
import org.springframework.format.FormatterRegistry;
31+
import org.springframework.format.Parser;
32+
import org.springframework.format.Printer;
2433
import org.springframework.format.support.DefaultFormattingConversionService;
2534
import org.springframework.format.support.FormattingConversionService;
2635
import org.springframework.util.StringValueResolver;
@@ -134,4 +143,36 @@ public static void addApplicationFormatters(FormatterRegistry registry) {
134143
registry.addFormatter(new IsoOffsetFormatter());
135144
}
136145

146+
/**
147+
* Add {@link GenericConverter}, {@link Converter}, {@link Printer}, {@link Parser}
148+
* and {@link Formatter} beans from the specified context.
149+
* @param registry the service to register beans with
150+
* @param beanFactory the bean factory to get the beans from
151+
* @since 2.2.0
152+
*/
153+
public static void addBeans(FormatterRegistry registry, ListableBeanFactory beanFactory) {
154+
Set<Object> beans = new LinkedHashSet<>();
155+
beans.addAll(beanFactory.getBeansOfType(GenericConverter.class).values());
156+
beans.addAll(beanFactory.getBeansOfType(Converter.class).values());
157+
beans.addAll(beanFactory.getBeansOfType(Printer.class).values());
158+
beans.addAll(beanFactory.getBeansOfType(Parser.class).values());
159+
for (Object bean : beans) {
160+
if (bean instanceof GenericConverter) {
161+
registry.addConverter((GenericConverter) bean);
162+
}
163+
else if (bean instanceof Converter) {
164+
registry.addConverter((Converter<?, ?>) bean);
165+
}
166+
else if (bean instanceof Formatter) {
167+
registry.addFormatter((Formatter<?>) bean);
168+
}
169+
else if (bean instanceof Printer) {
170+
registry.addPrinter((Printer<?>) bean);
171+
}
172+
else if (bean instanceof Parser) {
173+
registry.addParser((Parser<?>) bean);
174+
}
175+
}
176+
}
177+
137178
}

0 commit comments

Comments
 (0)