Spring 没有对转换器的注解支持,但您可以构建自己的。
您所需要的只是一个自定义限定符注解(让我们称之为@AutoRegistered
)和某种FormatterRegistrar
使用此@AutoRegistered
注解注册所有 Spring Beans 的 Converter/Formatter Registrar(实现)(以及一些用于注册此注册服务的 xml)。
然后,您需要使用此注释(以及其他一些注释以使其成为 Spring bean)来注释您的转换器,仅此而已。
@AutoRegistered
注解:
@Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface AutoRegistered {}
注册服务:
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.converter.Converter;
import org.springframework.format.FormatterRegistrar;
import org.springframework.format.FormatterRegistry;
public class AutoregisterFormatterRegistrar implements FormatterRegistrar {
/**
* All {@link Converter} Beans with {@link AutoRegistered} annotation.
* If spring does not find any matching bean, then the List is {@code null}!.
*/
@Autowired(required = false)
@AutoRegistered
private List<Converter<?, ?>> autoRegisteredConverters;
@Override
public void registerFormatters(final FormatterRegistry registry) {
if (this.autoRegisteredConverters != null) {
for (Converter<?, ?> converter : this.autoRegisteredConverters) {
registry.addConverter(converter);
}
}
}
}
注册商的 XML 配置:
<bean id="applicationConversionService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="formatterRegistrars">
<set>
<bean
class="AutoregisterFormatterRegistrar"
autowire="byType" />
</set>
</property>
</bean>
顺便说一句,对于您的枚举转换器,您不需要ConversionFactory
- 一个简单的转换器就足够了:
@AutoRegistered
@Component
public class EnumConverter implements Converter<Enum<?>, String> {
/** Use the same immutable value instead of creating an new array every time. */
private static final Object[] NO_PARAM = new Object[0];
/** The prefix of all message codes. */
private static final String PREFIX = "label_";
/** The separator in the message code, between different packages
as well as between package can class. */
private static final String PACKAGE_SEPARATOR = "_";
/** The separator in the message code, between the class name
and the enum case name. */
private static final String ENUM_CASE_SEPARATOR = "_";
/** The message source. */
private MessageSource messageSource;
@Autowired
public EnumConverter(final MessageSource messageSource) {
if (messageSource == null) {
throw new RuntimeException("messageSource must not be null");
}
this.messageSource = messageSource;
}
@Override
public String convert(final Enum<?> source) {
if (source != null) {
String enumValueName = source.name();
String code = PREFIX + source.getClass().getName().toLowerCase().
replace(".", PACKAGE_SEPARATOR)
+ ENUM_CASE_SEPARATOR + enumValueName.toLowerCase();
String message = messageSource.getMessage(code, NO_PARAM, enumValueName,
LocaleContextHolder.getLocale());
return message;
} else {
return "";
}
}
}