首页 > 编程语言 >Spring源码-finishBeanFactoryInitialization方法

Spring源码-finishBeanFactoryInitialization方法

时间:2022-09-18 19:34:50浏览次数:79  
标签:converterRegistry Spring public addConverter finishBeanFactoryInitialization sou

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));
}

	// Register a default embedded value resolver if no BeanFactoryPostProcessor
	// (such as a PropertySourcesPlaceholderConfigurer bean) registered any before:
	// at this point, primarily for resolution in annotation attribute values.
	if (!beanFactory.hasEmbeddedValueResolver()) {
		beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
	}

	// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
	String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
	for (String weaverAwareName : weaverAwareNames) {
		getBean(weaverAwareName);
	}

	// Stop using the temporary ClassLoader for type matching.
	beanFactory.setTempClassLoader(null);

	// Allow for caching all bean definition metadata, not expecting further changes.
	beanFactory.freezeConfiguration();

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

finishBeanFactoryInitialization方法设置ConversionService类型转换服务,还设置了EmbeddedValueResolver值处理器,用于解析value中存在的${}。初始化LoadTimeWeaverAware。冻结BeanDifinition信息。初始化非lazy的bean。

ConversionService接口的默认实现是DefaultConversionService,ConversionService里面主要保存了很多converter,由converter进行类型转换。

	public static void addDefaultConverters(ConverterRegistry converterRegistry) {
	addScalarConverters(converterRegistry);
	addCollectionConverters(converterRegistry);

	converterRegistry.addConverter(new ByteBufferConverter((ConversionService) converterRegistry));
	converterRegistry.addConverter(new StringToTimeZoneConverter());
	converterRegistry.addConverter(new ZoneIdToTimeZoneConverter());
	converterRegistry.addConverter(new ZonedDateTimeToCalendarConverter());

	converterRegistry.addConverter(new ObjectToObjectConverter());
	converterRegistry.addConverter(new IdToEntityConverter((ConversionService) converterRegistry));
	converterRegistry.addConverter(new FallbackObjectToStringConverter());
	converterRegistry.addConverter(new ObjectToOptionalConverter((ConversionService) converterRegistry));
}


  public static void addCollectionConverters(ConverterRegistry converterRegistry) {
	ConversionService conversionService = (ConversionService) converterRegistry;

	converterRegistry.addConverter(new ArrayToCollectionConverter(conversionService));
	converterRegistry.addConverter(new CollectionToArrayConverter(conversionService));

	converterRegistry.addConverter(new ArrayToArrayConverter(conversionService));
	converterRegistry.addConverter(new CollectionToCollectionConverter(conversionService));
	converterRegistry.addConverter(new MapToMapConverter(conversionService));

	converterRegistry.addConverter(new ArrayToStringConverter(conversionService));
	converterRegistry.addConverter(new StringToArrayConverter(conversionService));

	converterRegistry.addConverter(new ArrayToObjectConverter(conversionService));
	converterRegistry.addConverter(new ObjectToArrayConverter(conversionService));

	converterRegistry.addConverter(new CollectionToStringConverter(conversionService));
	converterRegistry.addConverter(new StringToCollectionConverter(conversionService));

	converterRegistry.addConverter(new CollectionToObjectConverter(conversionService));
	converterRegistry.addConverter(new ObjectToCollectionConverter(conversionService));

	converterRegistry.addConverter(new StreamConverter(conversionService));
}

    private static void addScalarConverters(ConverterRegistry converterRegistry) {
	converterRegistry.addConverterFactory(new NumberToNumberConverterFactory());

	converterRegistry.addConverterFactory(new StringToNumberConverterFactory());
	converterRegistry.addConverter(Number.class, String.class, new ObjectToStringConverter());

	converterRegistry.addConverter(new StringToCharacterConverter());
	converterRegistry.addConverter(Character.class, String.class, new ObjectToStringConverter());

	converterRegistry.addConverter(new NumberToCharacterConverter());
	converterRegistry.addConverterFactory(new CharacterToNumberFactory());

	converterRegistry.addConverter(new StringToBooleanConverter());
	converterRegistry.addConverter(Boolean.class, String.class, new ObjectToStringConverter());

	converterRegistry.addConverterFactory(new StringToEnumConverterFactory());
	converterRegistry.addConverter(new EnumToStringConverter((ConversionService) converterRegistry));

	converterRegistry.addConverterFactory(new IntegerToEnumConverterFactory());
	converterRegistry.addConverter(new EnumToIntegerConverter((ConversionService) converterRegistry));

	converterRegistry.addConverter(new StringToLocaleConverter());
	converterRegistry.addConverter(Locale.class, String.class, new ObjectToStringConverter());

	converterRegistry.addConverter(new StringToCharsetConverter());
	converterRegistry.addConverter(Charset.class, String.class, new ObjectToStringConverter());

	converterRegistry.addConverter(new StringToCurrencyConverter());
	converterRegistry.addConverter(Currency.class, String.class, new ObjectToStringConverter());

	converterRegistry.addConverter(new StringToPropertiesConverter());
	converterRegistry.addConverter(new PropertiesToStringConverter());

	converterRegistry.addConverter(new StringToUUIDConverter());
	converterRegistry.addConverter(UUID.class, String.class, new ObjectToStringConverter());
}

converter有三类实现,分别是Converter<S, T>,GenericConverter,ConverterFactory<S, R>。

@FunctionalInterface
public interface Converter<S, T> {

/**
 * Convert the source object of type {@code S} to target type {@code T}.
 * @param source the source object to convert, which must be an instance of {@code S} (never {@code null})
 * @return the converted object, which must be an instance of {@code T} (potentially {@code null})
 * @throws IllegalArgumentException if the source cannot be converted to the desired target type
 */
@Nullable
T convert(S source);

/**
 * Construct a composed {@link Converter} that first applies this {@link Converter}
 * to its input, and then applies the {@code after} {@link Converter} to the
 * result.
 * @param after the {@link Converter} to apply after this {@link Converter}
 * is applied
 * @param <U> the type of output of both the {@code after} {@link Converter}
 * and the composed {@link Converter}
 * @return a composed {@link Converter} that first applies this {@link Converter}
 * and then applies the {@code after} {@link Converter}
 * @since 5.3
 */
default <U> Converter<S, U> andThen(Converter<? super T, ? extends U> after) {
	Assert.notNull(after, "After Converter must not be null");
	return (S s) -> {
		T initialResult = convert(s);
		return (initialResult != null ? after.convert(initialResult) : null);
	};
}

}

Converter<S, T>由类型S转换成类型T。提供了一对一的转换服务。比如

class StringToTimeZoneConverter implements Converter<String, TimeZone> {

@Override
public TimeZone convert(String source) {
	return StringUtils.parseTimeZoneString(source);
}

}

GenericConverter提供了两种或多种类型之间的转换。

public interface GenericConverter {

/**
 * Return the source and target types that this converter can convert between.
 * <p>Each entry is a convertible source-to-target type pair.
 * <p>For {@link ConditionalConverter conditional converters} this method may return
 * {@code null} to indicate all source-to-target pairs should be considered.
 */
@Nullable
Set<ConvertiblePair> getConvertibleTypes();

/**
 * Convert the source object to the targetType described by the {@code TypeDescriptor}.
 * @param source the source object to convert (may be {@code null})
 * @param sourceType the type descriptor of the field we are converting from
 * @param targetType the type descriptor of the field we are converting to
 * @return the converted object
 */
@Nullable
Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType);


/**
 * Holder for a source-to-target class pair.
 */
final class ConvertiblePair {

	private final Class<?> sourceType;

	private final Class<?> targetType;

	/**
	 * Create a new source-to-target pair.
	 * @param sourceType the source type
	 * @param targetType the target type
	 */
	public ConvertiblePair(Class<?> sourceType, Class<?> targetType) {
		Assert.notNull(sourceType, "Source type must not be null");
		Assert.notNull(targetType, "Target type must not be null");
		this.sourceType = sourceType;
		this.targetType = targetType;
	}

	public Class<?> getSourceType() {
		return this.sourceType;
	}

	public Class<?> getTargetType() {
		return this.targetType;
	}

	@Override
	public boolean equals(@Nullable Object other) {
		if (this == other) {
			return true;
		}
		if (other == null || other.getClass() != ConvertiblePair.class) {
			return false;
		}
		ConvertiblePair otherPair = (ConvertiblePair) other;
		return (this.sourceType == otherPair.sourceType && this.targetType == otherPair.targetType);
	}

	@Override
	public int hashCode() {
		return (this.sourceType.hashCode() * 31 + this.targetType.hashCode());
	}

	@Override
	public String toString() {
		return (this.sourceType.getName() + " -> " + this.targetType.getName());
	}
}

}

比如:

final class ArrayToCollectionConverter implements ConditionalGenericConverter {

private final ConversionService conversionService;


public ArrayToCollectionConverter(ConversionService conversionService) {
	this.conversionService = conversionService;
}


@Override
public Set<ConvertiblePair> getConvertibleTypes() {
	return Collections.singleton(new ConvertiblePair(Object[].class, Collection.class));
}

@Override
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
	return ConversionUtils.canConvertElements(
			sourceType.getElementTypeDescriptor(), targetType.getElementTypeDescriptor(), this.conversionService);
}

@Override
@Nullable
public Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
	if (source == null) {
		return null;
	}

	int length = Array.getLength(source);
	TypeDescriptor elementDesc = targetType.getElementTypeDescriptor();
	Collection<Object> target = CollectionFactory.createCollection(targetType.getType(),
			(elementDesc != null ? elementDesc.getType() : null), length);

	if (elementDesc == null) {
		for (int i = 0; i < length; i++) {
			Object sourceElement = Array.get(source, i);
			target.add(sourceElement);
		}
	}
	else {
		for (int i = 0; i < length; i++) {
			Object sourceElement = Array.get(source, i);
			Object targetElement = this.conversionService.convert(sourceElement,
					sourceType.elementTypeDescriptor(sourceElement), elementDesc);
			target.add(targetElement);
		}
	}
	return target;
}

}

ConverterFactory<S, R>提供了从类型S到类型T的转换,类型T是R的子类或R。提供了从一种类型转换多种类型的服务。

final class StringToNumberConverterFactory implements ConverterFactory<String, Number> {

@Override
public <T extends Number> Converter<String, T> getConverter(Class<T> targetType) {
	return new StringToNumber<>(targetType);
}


private static final class StringToNumber<T extends Number> implements Converter<String, T> {

	private final Class<T> targetType;

	public StringToNumber(Class<T> targetType) {
		this.targetType = targetType;
	}

	@Override
	@Nullable
	public T convert(String source) {
		if (source.isEmpty()) {
			return null;
		}
		return NumberUtils.parseNumber(source, this.targetType);
	}
}

}

EmbeddedValueResolver是怎么加到beanFactory中的,是通过BeanFactoryPostProcessor加入的,比如PropertySourcesPlaceholderConfigurer。

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
	if (this.propertySources == null) {
		this.propertySources = new MutablePropertySources();
		if (this.environment != null) {
			this.propertySources.addLast(
				new PropertySource<Environment>(ENVIRONMENT_PROPERTIES_PROPERTY_SOURCE_NAME, this.environment) {
					@Override
					@Nullable
					public String getProperty(String key) {
						return this.source.getProperty(key);
					}
				}
			);
		}
		try {
			PropertySource<?> localPropertySource =
					new PropertiesPropertySource(LOCAL_PROPERTIES_PROPERTY_SOURCE_NAME, mergeProperties());
			if (this.localOverride) {
				this.propertySources.addFirst(localPropertySource);
			}
			else {
				this.propertySources.addLast(localPropertySource);
			}
		}
		catch (IOException ex) {
			throw new BeanInitializationException("Could not load properties", ex);
		}
	}

	processProperties(beanFactory, new PropertySourcesPropertyResolver(this.propertySources));
	this.appliedPropertySources = this.propertySources;
}


    	protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess,
		final ConfigurablePropertyResolver propertyResolver) throws BeansException {

	propertyResolver.setPlaceholderPrefix(this.placeholderPrefix);
	propertyResolver.setPlaceholderSuffix(this.placeholderSuffix);
	propertyResolver.setValueSeparator(this.valueSeparator);

	StringValueResolver valueResolver = strVal -> {
		String resolved = (this.ignoreUnresolvablePlaceholders ?
				propertyResolver.resolvePlaceholders(strVal) :
				propertyResolver.resolveRequiredPlaceholders(strVal));
		if (this.trimValues) {
			resolved = resolved.trim();
		}
		return (resolved.equals(this.nullValue) ? null : resolved);
	};

	doProcessProperties(beanFactoryToProcess, valueResolver);
}

    protected void doProcessProperties(ConfigurableListableBeanFactory beanFactoryToProcess,
		StringValueResolver valueResolver) {

	BeanDefinitionVisitor visitor = new BeanDefinitionVisitor(valueResolver);

	String[] beanNames = beanFactoryToProcess.getBeanDefinitionNames();
	for (String curName : beanNames) {
		// Check that we're not parsing our own bean definition,
		// to avoid failing on unresolvable placeholders in properties file locations.
		if (!(curName.equals(this.beanName) && beanFactoryToProcess.equals(this.beanFactory))) {
			BeanDefinition bd = beanFactoryToProcess.getBeanDefinition(curName);
			try {
				visitor.visitBeanDefinition(bd);
			}
			catch (Exception ex) {
				throw new BeanDefinitionStoreException(bd.getResourceDescription(), curName, ex.getMessage(), ex);
			}
		}
	}

	// New in Spring 2.5: resolve placeholders in alias target names and aliases as well.
	beanFactoryToProcess.resolveAliases(valueResolver);

	// New in Spring 3.0: resolve placeholders in embedded values such as annotation attributes.
	beanFactoryToProcess.addEmbeddedValueResolver(valueResolver);
}

例子:
DateConversionService

public class DateConversionService implements Converter<String, Date> {
@Override
public Date convert(String source) {
	if (source != null) {
		SimpleDateFormat format = new SimpleDateFormat("YYYY-MM-DD");
		try {
			return format.parse(source);
		} catch (ParseException e) {
			e.printStackTrace();
		}
	}
	return null;
}
}

自定义转换器将字符串转成日期。

public class Person {
private String name;

private Date birthday;

public String getName() {
	return name;
}

public void setName(String name) {
	this.name = name;
}

public Date getBirthday() {
	return birthday;
}

public void setBirthday(Date birthday) {
	this.birthday = birthday;
}

@Override
public String toString() {
	return "Person{" +
			"name='" + name + '\'' +
			", birthday=" + birthday +
			'}';
}
}

conversionService.xml

     <bean id="person" class="conversionService.Person">
		 <property name="name" value="张三"/>
	     <property name="birthday" value="2022-01-01"/>
  </bean>

<bean id="dateConversionService" class="conversionService.DateConversionService"></bean>

<bean id="conversionService"
	  class="org.springframework.context.support.ConversionServiceFactoryBean">
	<property name="converters">
		<set>
			<ref bean="dateConversionService"/>
		</set>
	</property>
</bean>

测试:

ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("conversionService.xml");
Person bean = context.getBean(Person.class);
System.out.println(bean);

标签:converterRegistry,Spring,public,addConverter,finishBeanFactoryInitialization,sou
From: https://www.cnblogs.com/shigongp/p/16705190.html

相关文章