Spring @Value 使用,初始化一个 POJO 对象默认值

tech2022-07-07  212

说一下思路,方法

@Value 注入参数数值

 最基础的使用方式

@Value("${some.key:my default value}") private String stringWithDefaultValue;

 当然@value 还可以 注入List、Map等,可以看这里

https://www.baeldung.com/spring-value-annotation

如果想初始化带有一个pojo的map怎么办?比如给

HashMap<String, Student>

默认值 

{"studentOne":{"age":"25","name":"老王"}}

我们创建的默认值是String,然后我们需要转成对应的类

创建类Student:

public class Student { private int age; private String name; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } }

我们需要引入 Spring类型转换(Converter)

可以看https://www.cnblogs.com/baka-sky/archive/2018/12/30/10200845.html 或者其他文章学习

创建两个转换类:

import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.type.TypeFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.converter.ConditionalGenericConverter; import org.springframework.stereotype.Component; import java.io.IOException; import java.util.Collection; import java.util.HashSet; import java.util.Map; import java.util.Set; @Component public class BeanGenericConverterConfig implements ConditionalGenericConverter { private static final Logger LOGGER = LoggerFactory.getLogger(BeanGenericConverterConfig.class); protected static final Set<ConvertiblePair> CONVERTIBLE_TYPES = new HashSet<>(); protected final ObjectMapper objectMapper; /** * Constructor. */ public BeanGenericConverterConfig() { this.objectMapper = new ObjectMapper(); } /** * Add convertible types to this converter. * * @param set Set for convertible types. */ public void addConvertibleTypes(Set<ConvertiblePair> set) { CONVERTIBLE_TYPES.addAll(set); } /** * Get a set for convertible types. * * @return Set for convertible types. */ @Override public Set<ConvertiblePair> getConvertibleTypes() { return CONVERTIBLE_TYPES; } /** * Determine whether object can be converted. * * @param sourceType Source type. * @param targetType Target type. * @return True if the type matches, otherwise false. */ @Override public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) { return CONVERTIBLE_TYPES.stream().anyMatch(p -> p.getTargetType() == targetType.getType()); } /** * Convert String to concrete bean instance. * * @param source Object to be converted. * @param sourceType Source type. * @param targetType Target type. * @return Converted bean object. */ @Override public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { Object value = null; try { final Class<?> clazz = targetType.getType(); if (Map.class.isAssignableFrom(clazz) || Collection.class.isAssignableFrom(clazz)) { value = convertContainerBean(source, targetType); } else { value = convertObjectBean(source, targetType); } } catch (Exception e) { String exceptionMessage = "Failed to convert a bean for " + targetType.getResolvableType().toString(); LOGGER.error(exceptionMessage, e); } return value; } /** * Convert object to concrete bean. * * @param source Source type. * @param targetType Target type. * @return Converted bean object. * @throws IOException Exception during conversion. */ private Object convertObjectBean(Object source, TypeDescriptor targetType) throws IOException { Class targetClazz = targetType.getResolvableType().getGenerics()[0].getRawClass(); return objectMapper.readValue(source.toString(), targetClazz); } /** * Convert object to map or list bean. * * @param source Source type. * @param targetType Target type. * @return Converted bean object. * @throws IOException Exception during conversion. */ private Object convertContainerBean(Object source, TypeDescriptor targetType) throws IOException { return objectMapper.readValue(source.toString(), TypeFactory.defaultInstance().constructFromCanonical(targetType.getResolvableType().toString())); } } import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.converter.GenericConverter.ConvertiblePair; import org.springframework.core.convert.support.DefaultConversionService; import java.util.HashMap; import java.util.HashSet; import java.util.Set; @Configuration public class BeanConverterConfig { protected static final Set<ConvertiblePair> CONVERTIBLE_PAIRS = new HashSet<>(); /** * Initialize the static variable CONVERTIBLE_PAIRS. */ static { CONVERTIBLE_PAIRS.add(new ConvertiblePair(String.class, HashMap.class)); } @Bean public BeanFactoryPostProcessor coreBeanFactoryPostProcessor(BeanGenericConverterConfig converter) { return beanFactory -> { ConversionService conversionService = beanFactory.getConversionService(); if (conversionService == null) { conversionService = DefaultConversionService.getSharedInstance(); beanFactory.setConversionService(conversionService); } converter.addConvertibleTypes(CONVERTIBLE_PAIRS); ((DefaultConversionService) conversionService).addConverter(converter); }; } }

 

这块大体是需要matches方法进行判断之后进行转换,如果你想直接转换Student单个对象,需要自己进行格外进行处理

@Value 具体源码 

https://www.jianshu.com/p/933669270a9f

org.springframework.beans.factory.support.DefaultListableBeanFactory#doResolveDependency

这块很重要。

创建ConfigService:

import com.example.demo.entity.Student; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import java.util.HashMap; @Configuration public class ConfigService { @Value("${init.student}") private HashMap<String, Student> student; public HashMap<String, Student> getStudent() { return student; } }

更新application.properties

init.student={"studentOne":{"age":"25","name":"老王"}}

 

 

 

 

 

 

 

 

 

 

最新回复(0)