1

我正在使用反射代理对公共 API 执行额外的检查。本质上,我想包装从它返回的每个对象,以便调用者获得的任何对象都是真实对象的代理。

Java 仍然存在整个擦除问题,因此我将传递包装对象的类型。我应该知道一切是什么类型,因为 API 的入口是一个单一的、非通用的接口。

public class ProxyInvocationHandler implements InvocationHandler {
    private final Object delegate;
    private final Type delegateType;

    public ProxyInvocationHandler(Object delegate, Type delegateType) {
        this.delegate = delegate;
        this.delegateType = delegateType;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) {
        // Omitted: additional checks performed here.

        Object result = method.invoke(delegate, args);

        Type returnType = method.getGenericReturnType();

        // e.g. if delegateType is List<Cat> and the method is the get method,
        // returnType would be E but resultType should be Cat.
        Type resultType = ???

        // Utility method I will omit, it just creates another proxy instance
        // using its own invocation handler.
        return ProxyUtils.wrap(result, resultType);
    }
}

我环顾了 Type / ParametrizedType API,似乎无法找到一种方法来获取resultType,即使delegateType并且returnType应该有足够的信息来计算它。

这样做的“正确”方法是什么?

4

2 回答 2

1

您可以为此目的使用Java ClassMate 。您必须使用com.fasterxml.classmate.GenericType类型标记:

GenericType<?> delegateType = new GenericType<List<Cat>>() {};

{}请注意称为“超类型令牌”模式的空。

TypeResolver typeResolver = new TypeResolver();
MemberResolver memberResolver = new MemberResolver(

ResolvedType type = typeResolver.resolve(delegateType);
ResolvedTypeWithMembers members = memberResolver.resolve(type, null, null);
ResolvedMethod[] methods = members.getMemberMethods();

将结果缓存在Map

Map<Method, ResolvedMethod> resolved = new HashMap<>();
for (ResolvedMethod method: methods) {
    resolved.put(method.getRawMember(), method);
}

现在,当你有一个由delegateType, ie声明的方法时List,你可以得到它的解析返回类型:

Method method = List.class.getMethod("get", int.class);
ResolvedType resultType = resolved.get(method).getReturnType();
System.out.println("resultType = " + resultType);              // prints resultType = Cat
于 2012-09-25T15:13:50.013 回答
1

以下是番石榴的方式,适用于未来的人:

...
Type returnType = method.getGenericReturnType();
TypeToken<?> resultType = TypeToken.of(delegateType).resolveType(returnType);

我将 delegateType 的类型更改TypeToken<?>为让事情变得更容易一些。当然,我添加了相当多的缓存(使用 a LoadingCache)以将性能降低到合理的速度。他们的解析代码比我最初做同样事情的破解代码慢。不同的是,我现在有信心正确地完成它。

于 2012-09-28T06:20:37.383 回答