Spring does not have annotation support for Converters, but you can build your own.
All you need is an custom qualifier annotation (lets call it @AutoRegistered
) and some kind of Converter/Formatter Registrar (implements FormatterRegistrar
) that registers all the Spring Beans with this @AutoRegistered
annotation (and some xml to register this registration service).
Then you need to annotate your conveter with this annotation (and some other annotation to make it
a spring bean) and that is all.
@AutoRegistered
annotation:
@Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface AutoRegistered {}
Registration service:
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 configuration for the registrar:
<bean id="applicationConversionService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="formatterRegistrars">
<set>
<bean
class="AutoregisterFormatterRegistrar"
autowire="byType" />
</set>
</property>
</bean>
BTW for your enum converter you do not need a ConversionFactory
- a simple converter is enough:
@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 "";
}
}
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…