如何在 spring 属性文件中使用嵌套的 java.reflect.Type

How to use a nested java.reflect.Type in a spring properties file

最近遇到一个案例,我想要预先但可配置的类型(长话短说)。通常我这样做

Type t = new TypeToken<ArrayList<Integer>>() {}.getType();

我想将右侧放入我的 spring 属性文件中,然后发出与此类似的调用:

Type t = env.getProperty("type-property");

或者使用@ConfigurationProperties。

我通常使用@ConfigurationProperties,但我所在的存储库没有它。如果第一种方法根本不可能,我可以考虑引入依赖项,但阻力最小的路径更可取。

我尝试了以下带有尖括号、圆括号和方括号的 属性 定义的一些变体 --- none 成功了。

type-property=java.util.ArrayList<java.lang.Integer>

对于您被迫用于解决此问题的各种搜索词,我很难得到任何有用的信息。我发现了这个相关的问题,但没有运气将它翻译成非 xml 配置(我也不能在这个项目中做 xml 风格)。 link: Create a Guava TypeToken in Spring xml config?

编辑: 使用@LppEdd 提供的答案,我对 de/serialization:

使用了以下调用
Type sampleType = new TypeToken<HashSet<ArrayList<Integer>>>() {}.getType();
// serialize via java.lang.reflect.Type.getTypeName()
String serializedType = sampleType.getTypeName();
// above string value is "java.util.HashSet<java.util.ArrayList<java.lang.Integer>>"
// deserialize via org.eclipse.jetty.util.TypeUtil.fromName(String name)
Type sampleTypeAgain = TypeUtil.fromName(serializedType);

回答您的 "translating to Java" 点:

@Bean
@Qualifier("IntegerArrayList")
public Type integerArrayList() {
   return new TypeToken<ArrayList<Integer>>() {}.getType();
}

用法:

@Autowired
@Qualifier("IntegerArrayList")
private Type type;

或者...

我会帮你开始的。
"better" 方法是将 @ConfigurationProperties 与自定义 PropertySource 实现结合使用。所有 Type 子 类 都应该是可序列化的,因此您可以存储序列化数据并即时反序列化。

显然,字段名称将对应于 Type(s) 个映射键。

class TypePropertySource extends PropertySource<TypeSource> {
    private final TypeSource source;

    TypePropertySource(final TypeSource source) {
        super("a-name", source);
        this.source = source;
    }

    @Override
    public Object getProperty(final String name) {
        try {
            return (Type) source.getAndDeserialize(name);
        } catch (final Exception e) {
            // Recover or do nothing.
        }

        return null;
    }
}

编辑:我真的不知道 Spring 中的 属性 值是否支持 String 以外的类型。

您是否考虑过使用 Spring SPEL?它几乎可以为您完成解决方案,除非由于对泛型的支持不佳,您需要为 TypeToken.

的每个子 class 创建单独的 class

例如具体 class 的 :

import java.util.ArrayList;
import com.google.common.reflect.TypeToken;

public class MyType extends TypeToken< ArrayList<Integer> >{

}

你可以 属性 这样:

type-property: new com.comcast.viser.ipPreference.web.MyType().getType()

然后像这样注入:

@Value("#{${type-property}}")
private java.lang.reflect.Type type;