spring中TypeConverter对象解析

[TOC] ###TypeConverter在同期容器中的创建及初始化 spring的容器中有很多地方会用的类型转换,spring使用TypeConverter做类型转换,现在我们来分析TypeConverter是如何在spring的容器中使 在AbstractBeanFactory对象下面定义了属性typeConverter,代码如下:

	/** A custom TypeConverter to use, overriding the default PropertyEditor mechanism */
	private TypeConverter typeConverter;

会覆盖默认PropertyEditor机制,该对象可以设置一个自定义的对象,如果没有设置,会使用SimpleTypeConverter作为默认实现类, 同时会将beanFatory中定义的两个属性

	/** Custom PropertyEditorRegistrars to apply to the beans of this factory */
	private final Set propertyEditorRegistrars =
			new LinkedHashSet(4);
	/** Custom PropertyEditors to apply to the beans of this factory */
	private final Map, Class> customEditors =
			new HashMap, Class>(4);

设置到TypeConverter的属性

	private Map, PropertyEditor> customEditors;

中,会将beanFatory定义的属性

	/** Spring ConversionService to use instead of PropertyEditors */
	private ConversionService conversionService;

设置到TypeConverter的属性

	private ConversionService conversionService;

中,获取该对象的相关方法如下:

方法1:

	/**
     * 获取BeanFactory中的属性typeConverter。如果属性typeConverter为空,
     * 那么每次都会创建一个SimpleTypeConverter对象,因为内部使用的是PropertyEditor作为类型转换,
     * PropertyEditor通常不是线程安全的,因为内部是有状态的。如果默认的PropertyEditor机制是激活的,
     * 返回的的TypeConverter对象中能够感知到已经注册的custom editors。
	 * Obtain a type converter as used by this BeanFactory. This may be a fresh
	 * instance for each call, since TypeConverters are usually not thread-safe.
	 * 

If the default PropertyEditor mechanism is active, the returned * TypeConverter will be aware of all custom editors that have been registered. * @since 2.5 */ @Override public TypeConverter getTypeConverter() { TypeConverter customConverter = getCustomTypeConverter(); if (customConverter != null) { return customConverter; } else { // Build default TypeConverter, registering custom editors. SimpleTypeConverter typeConverter = new SimpleTypeConverter(); typeConverter.setConversionService(getConversionService()); registerCustomEditors(typeConverter); return typeConverter; } }

方法2:

     /**
	 * 返回自定义的TypeConverter
	 * Return the custom TypeConverter to use, if any.
	 * @return the custom TypeConverter, or {@code null} if none specified
	 */
	protected TypeConverter getCustomTypeConverter() {
		return this.typeConverter;
	}

方法3:

	/**
     * 初始化TypeConvert对象,向其注册customEditors,customEditors在BeanFactory中可以被注册进来的。
     * customEditors在BeanWrappers中会使用到来转换bean的属性;也会在创建bean的时候转换构造函数的参数或者工厂方法的参数。
     * 官方解析:
	 * Initialize the given PropertyEditorRegistry with the custom editors
	 * that have been registered with this BeanFactory.
	 * 

To be called for BeanWrappers that will create and populate bean * instances, and for SimpleTypeConverter used for constructor argument * and factory method type conversion. * @param registry the PropertyEditorRegistry to initialize */ protected void registerCustomEditors(PropertyEditorRegistry registry) { PropertyEditorRegistrySupport registrySupport = (registry instanceof PropertyEditorRegistrySupport ? (PropertyEditorRegistrySupport) registry : null); if (registrySupport != null) { registrySupport.useConfigValueEditors(); } if (!this.propertyEditorRegistrars.isEmpty()) { //将属性beanFactory的属性propertyEditorRegistrars注册到TypeConvert的属性CustomEditors中 for (PropertyEditorRegistrar registrar : this.propertyEditorRegistrars) { try { registrar.registerCustomEditors(registry); } catch (BeanCreationException ex) { //... } } } if (!this.customEditors.isEmpty()) { //将属性beanFactory的属性customEditors注册到TypeConvert的属性CustomEditors中 for (Map.Entry, Class> entry : this.customEditors.entrySet()) { Class requiredType = entry.getKey(); Class editorClass = entry.getValue(); registry.registerCustomEditor(requiredType, BeanUtils.instantiateClass(editorClass)); } } }

###spring容器中配置customEditors,propertyEditorRegistrars,conversionService对象。 下面看一下在beanFactory中是如何设置customEditors,propertyEditorRegistrars,conversionService对象的。

1.设置conversionService对象。

只要设置一个id=conversionService的bean就可以了,spring会自动注册到beanFactory的conversionService中来,源码分析如下:

我们知道spring的高级容器,如ClassPathXmlApplicationContext,会在刚开始就刷新容器,调用refresh方法,初始化所有的bean, refresh方法在AbstractApplicationContext类中定义,代码如下

	@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				initMessageSource();

				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				onRefresh();

				// Check for listener beans and register them.
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				finishRefresh();
			}

			catch (BeansException ex) {
				logger.warn("Exception encountered during context initialization - cancelling refresh attempt", ex);

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}
		}
	}

其中会调用finishBeanFactoryInitialization方法,代码如下:

	/**
	 * Finish the initialization of this context's bean factory,
	 * initializing all remaining singleton beans.
	 */
	protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
		// Initialize conversion service for this context.
		if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
				beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
			beanFactory.setConversionService(
					beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
		}
		//···
	}

这段代码也是醉了,直接判断beanFactory中时候有名字为conversionService的bean,有的话就获取出来设置到conversionService属性中。

2.设置customEditors,propertyEditorRegistrars属性

我们知道如果要设置beanFactoy中定义的属性有几种方法,第一种就是上面提到的spring硬编码写死是哪个bean,还有一种就是实现BeanFactoryPostProcessor接口, 在上面的方法refresh中有句代码


    // Invoke factory processors registered as beans in the context.
    invokeBeanFactoryPostProcessors(beanFactory);

该方法的具体内容:

	/**
	 * Instantiate and invoke all registered BeanFactoryPostProcessor beans,
	 * respecting explicit order if given.
	 * 

Must be called before singleton instantiation. */ protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) { PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()); }

spring的高级中在创建bean之前会提前调用所有实现了BeanFactoryPostProcessor接口的bean.

spring中实现了一个bean用于向beanFactory中注册这个属性:org.springframework.beans.factory.config.CustomEditorConfigurer,参考配置如下

  
 
   
     
       
       
     
   
 
 
 

在AbstractApplicationContext中有个方法prepareBeanFactory,也帮我们默认注册了一些资源相关的ropertyEditor对象,相关代码如下

beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrResourceEditorRegistrar(this, getEnvironment()));

###typeConverter对象解析 在spring中一开始是使用PropertyEditor对象来进行类型转换的,PropertyEditor对象有一些问题,只能转换字符串到对象,而且不是线程安全的,所以spring中重新新定义了 一个对象Converter由于类型转换,可以进行任意类型的转换,对外使用ConversionService,而TypeConverter对象正好是综合了这两个对象, 先尝试是用PropertyEditor转换器转换,如果没找到对应的转换器,会用ConversionService来进行对象转换。 TypeConverter接口描述如下:

/**
 * Interface that defines type conversion methods. Typically (but not necessarily)
 * implemented in conjunction with the {@link PropertyEditorRegistry} interface.
 *
 * 

Note: Since TypeConverter implementations are typically based on * {@link java.beans.PropertyEditor PropertyEditors} which aren't thread-safe, * TypeConverters themselves are not to be considered as thread-safe either. * * @author Juergen Hoeller * @since 2.0 * @see SimpleTypeConverter * @see BeanWrapperImpl */

由此可见,TypeConverter并不是线程安全的,虽然不是线程安全的,但是并不代表就不能使用,我们只要在使用的时候都重新创建一下就可以了, 正如上文的getTypeConverter方法一样。

转载于:https://my.oschina.net/u/2298333/blog/656004

你可能感兴趣的:(spring中TypeConverter对象解析)