我正在尝试使用spell来获取表达式的类型而不是实际的实例值。我不认为这是可能的,但我想把它扔出去。
考虑:
public interface Foo {
Integer getAge();
String getFamilyName();
String getGivenName();
Set<Integer> getSomeData();
Set<Baz> getBazez();
Baz getAnyBaz();
}
public interface Baz {
Integer getBat();
Integer getWhatever();
}
一些测试
@Test
public void testNestedMemberDataType() throws Exception {
ExpressionParser parser = new SpelExpressionParser();
EvaluationContext context = new StandardEvaluationContext();
Expression exp = parser.parseExpression("anyBaz.bat");
Class<?> valueType = exp.getValueType(context);
assertEquals(Integer.class,valueType);
}
@Test
public void testNestedMemberDataTypeSet() throws Exception {
ExpressionParser parser = new SpelExpressionParser();
EvaluationContext context = new StandardEvaluationContext();
// this is not valid spell syntax but I would like to do this
// to indicate the type inside the collection
Expression exp = parser.parseExpression("bazez[*].bat");
Class<?> valueType = exp.getValueType(context);
assertEquals(Integer.class,valueType);
}
答案 0 :(得分:0)
我最终实际上是这样实现的:
@Override
public Class<?> getDeclaredTypeFor(String attribute) {
Class<?> finalType = entityType;
List<String> nestings = Arrays.asList(attribute.split("\\."));
PropertyDescriptor d = null;
Iterator<String> iter = nestings.iterator();
while (iter.hasNext()) {
String nesting = iter.next();
d = BeanUtils.getPropertyDescriptor(finalType, nesting);
if (d == null) {
Set<Class> allTypes = allTypesFor(finalType, new LinkedHashSet<>());
d = allTypes.stream().map(t -> BeanUtils.getPropertyDescriptor(t, nesting)).filter(p -> p != null).findFirst().orElse(null);
if (d == null)
break;
}
if (iter.hasNext() && isTypeACollection(d.getReadMethod().getGenericReturnType())) {
finalType = getGenericType(d.getReadMethod().getGenericReturnType(), true);
} else {
finalType = d.getPropertyType();
}
}
return d == null ? null : finalType;
}
private Class getGenericType(Type t, boolean isCollection) {
Class clazz;
if (isCollection) {
Type type = ((ParameterizedType) t).getActualTypeArguments()[0];
if (type instanceof WildcardType) {
type = ((WildcardType) type).getUpperBounds()[0];
} else if(type instanceof TypeVariable) {
type = ((TypeVariable) type).getBounds()[0];
}
clazz = (Class) type;
} else if (t instanceof Class) {
clazz = (Class) t;
} else {
throw new RuntimeException("Don't know how to handle " + t.getClass());
}
return clazz;
}
private boolean isTypeACollection(Type t) {
boolean isPossible = t instanceof ParameterizedType;
if (isPossible)
isPossible = Collection.class.isAssignableFrom((Class) ((ParameterizedType) t).getRawType());
return isPossible;
}
private static Set<Class> allTypesFor(Class c, Set<Class> types) {
types.add(c);
Class superclass = c.getSuperclass();
if (superclass != null)
allTypesFor(superclass, types);
for (Class iFace : c.getInterfaces()) {
allTypesFor(iFace, types);
}
return types;
}