zoukankan      html  css  js  c++  java
  • spring 之 类型转换

    在spring中, 提供了至少三种的 类型转换方式:   ConversionServiceFactoryBean, FormattingConversionServiceFactoryBean, CustomEditorConfigurer。

    方式一:ConversionServiceFactoryBean 

    ConversionServiceFactoryBean 的用法是: 

        <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
            <property name="converters" >
                <list>
                    <bean class="com.lk.StringToDateConverter">
                        <constructor-arg type="java.lang.String" value="MM-dd-yyyy"/>
                    </bean>
                </list>
            </property>
        </bean>


    public class StringToDateConverter implements Converter<String, Date> {
    private Logger logger = Logger.getLogger(StringToDateConverter.class.getName());
    private String datePattern;
    public StringToDateConverter(String datePattern){
    this.datePattern = datePattern; System.out.println("instantiating...converter with pattern : " + datePattern);
    }

    public Date convert(String source) {
    System.out.println("StringToDateConverter.convert");
    try {
    SimpleDateFormat sdf = new SimpleDateFormat(datePattern);
    sdf.setLenient(false);
    return sdf.parse(source);
    } catch (ParseException e) {
    e.printStackTrace();
    logger.info("date parse exception.");
    }
    return null;
    }
    }

    方式二:FormattingConversionServiceFactoryBean

    FormattingConversionServiceFactoryBean 跟ConversionServiceFactoryBean差不多, 也是需要bean 的名字必须是 conversionService

        <bean id="dateFormatter" class="com.lk.DateFormatter" >
            <constructor-arg index="0" value="yyyy-MM-dd"></constructor-arg>
        </bean>
    
    
        <bean id="conversionService"
              class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
            <property name="formatters">
                <set>
                    <!-- 这里是我们自己定义的类型转换器 -->
                    <!-- 注意,这里首字母要小写,因为springmvc帮我们创建bean的时候,是以类名首字母小写命名 -->
                    <ref bean="dateFormatter"/>
                </set>
            </property>
        </bean>

    上面,bean 的名字必须是 conversionService , spring会去获取这个名字的bean ,找到了就注册为转换器。 其converters 属性中, 我们可以添加一些自定义的类型转换器。

     至于为什么?

    public class FormattingConversionServiceFactoryBean implements FactoryBean<FormattingConversionService>, EmbeddedValueResolverAware, InitializingBean {
        private Set<?> converters;// 通过setter 设置
        private Set<?> formatters;// 通过setter 设置
        private Set<FormatterRegistrar> formatterRegistrars;// 可空,不为空的话, 注册 conversionService
        private boolean registerDefaultFormatters = true;
        private StringValueResolver embeddedValueResolver;
        private FormattingConversionService conversionService;
    
    ...
    
        public void afterPropertiesSet() {
            this.conversionService = new DefaultFormattingConversionService(this.embeddedValueResolver, this.registerDefaultFormatters);
            ConversionServiceFactory.registerConverters(this.converters, this.conversionService); // 同时注册converter,和 conversionService
            this.registerFormatters();// 注册 formatter
        }
    
        private void registerFormatters() {
            Iterator var1;
            if(this.formatters != null) {
                var1 = this.formatters.iterator();
    
                while(var1.hasNext()) {
                    Object registrar = var1.next();
                    if(registrar instanceof Formatter) {
                        this.conversionService.addFormatter((Formatter)registrar); // 注册 formater其实就是把 formatter 添加到 conversionService中
                    } else {
                        if(!(registrar instanceof AnnotationFormatterFactory)) {
                            throw new IllegalArgumentException("Custom formatters must be implementations of Formatter or AnnotationFormatterFactory");
                        }
    
                        this.conversionService.addFormatterForFieldAnnotation((AnnotationFormatterFactory)registrar);
                    }
                }
            }
    
            if(this.formatterRegistrars != null) {
                var1 = this.formatterRegistrars.iterator();
    
                while(var1.hasNext()) {
                    FormatterRegistrar registrar1 = (FormatterRegistrar)var1.next();
                    registrar1.registerFormatters(this.conversionService);
                }
            }
    
        }
    
    ...

    位于AbstractApplicationContext:

        protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
            if(beanFactory.containsBean("conversionService") && beanFactory.isTypeMatch("conversionService", ConversionService.class)) {
                beanFactory.setConversionService((ConversionService)beanFactory.getBean("conversionService", ConversionService.class));
            }
    ...

    可见, bean 为 conversionService 且是一个  ConversionService 类型, 或其子类,就会生效。

    上面的beanFactory 其实是AbstractBeanFactory ,它拥有很多有用的属性, 用于spring IoC 

    public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
        private BeanFactory parentBeanFactory;
        private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
        private ClassLoader tempClassLoader;
        private boolean cacheBeanMetadata = true;
        private BeanExpressionResolver beanExpressionResolver;
        private ConversionService conversionService;
        private final Set<PropertyEditorRegistrar> propertyEditorRegistrars = new LinkedHashSet(4);
        private final Map<Class<?>, Class<? extends PropertyEditor>> customEditors = new HashMap(4);
        private TypeConverter typeConverter;
        private final List<StringValueResolver> embeddedValueResolvers = new LinkedList();
        private final List<BeanPostProcessor> beanPostProcessors = new ArrayList();
        private boolean hasInstantiationAwareBeanPostProcessors;
        private boolean hasDestructionAwareBeanPostProcessors;
        private final Map<String, Scope> scopes = new LinkedHashMap(8);
        private SecurityContextProvider securityContextProvider;
        private final Map<String, RootBeanDefinition> mergedBeanDefinitions = new ConcurrentHashMap(256);
        private final Set<String> alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap(256));
        private final ThreadLocal<Object> prototypesCurrentlyInCreation = new NamedThreadLocal("Prototype beans currently in creation");
    ...

    方式三:CustomEditorConfigurer

    CustomEditorConfigurer bean 的id 是可选的, 或者任意值都是ok 的。 但是他的配置稍微有些复杂, 它需要指定 customEditors 每一个 自定义转换器的entry的 类型。 比如, 如果我们需要把 String 转换为 java.util.Date, 那么需要指定 java.util.Date 为entry ,Spring 再尝试做转换的时候,会去 找到这个 entry 的转换器 然后转换它。 它的value 是 FQN, 这样的话,就不能配置转换器的 属性了,那么只能在转换器内部设置java 编码的 属性了。

        <bean id="anyIdOrName"
              class="org.springframework.beans.factory.config.CustomEditorConfigurer">
            <property name="customEditors">
                <map>
                    <entry key="java.util.Date">
                        <value>com.lk.UtilDatePropertyEditor</value>
                    </entry>
                </map>
            </property>
        </bean>

     为什么不需要id 呢?因为:

    public class CustomEditorConfigurer implements BeanFactoryPostProcessor, Ordered { 它实现了 BeanFactoryPostProcessor
        protected final Log logger = LogFactory.getLog(this.getClass());
        private int order = 2147483647;
        private PropertyEditorRegistrar[] propertyEditorRegistrars;
        private Map<Class<?>, Class<? extends PropertyEditor>> customEditors; // 专门用来注册 客户化自定义的 editors 


    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { // 这里有一个 beanFactory参数
    if(this.propertyEditorRegistrars != null) {
    PropertyEditorRegistrar[] var2 = this.propertyEditorRegistrars;
    int entry = var2.length;

    for(int requiredType = 0; requiredType < entry; ++requiredType) {
    PropertyEditorRegistrar propertyEditorClass = var2[requiredType];
    beanFactory.addPropertyEditorRegistrar(propertyEditorClass);
    }
    }

    if(this.customEditors != null) {
    Iterator var6 = this.customEditors.entrySet().iterator();

    while(var6.hasNext()) {
    Entry var7 = (Entry)var6.next();
    Class var8 = (Class)var7.getKey();
    Class var9 = (Class)var7.getValue();
    beanFactory.registerCustomEditor(var8, var9); // 实际添加到了 AbstractBeanFactory 
    }
    }

    }

  • 相关阅读:
    原型
    构造函数
    异常处理
    逻辑中断
    1. 两数之和
    面向对象(进阶篇)
    面向对象(初级篇)
    面向对象
    迭代器/生成器
    模块&字符格式化
  • 原文地址:https://www.cnblogs.com/FlyAway2013/p/7856041.html
Copyright © 2011-2022 走看看