简体   繁体   English

Java 从接口中提取带有反射的泛型类型参数

[英]Java extract generic type parameters with reflection from interface

I'm writing a custom Java annotation for processing CrudRepositories with Reflection in Java Spring. With the org.reflections.reflections library.我正在编写自定义 Java 注释,用于在 Java Spring 中使用反射处理 CrudRepositories。使用 org.reflections.reflections 库。 I'm getting all interfaces annotated with my annotation as a class file like so:我将所有接口都用我的注释作为 class 文件进行注释,如下所示:

Reflections reflections = new Reflections("basePackage");
Set<Class<?>> annotated = reflections.getTypesAnnotatedWith(MyAnnotation.class);

Only interfaces, which at some point extend JpaRepository are annotated with my @MyAnnotation at the class level.只有在某些时候扩展 JpaRepository 的接口在 class 级别用我的@MyAnnotation注释。


My repository structure is as follows: There are two cases,我的存储库结构如下:有两种情况,

first case:第一种情况:
public interface SomeRepo extends JpaRepository<SomeEntity, Long> {...}

the second case is composed out of a inheritance hierarchy:第二种情况由 inheritance 层次结构组成:
public interface SuperClassRepo <T extends SomeRandomEntity> extends JpaRepository<T, String> {...}
public interface SubClassRepo extends SuperClassRepo<SubEntityOfSomeRandomEntity> {...}

My goal is now to extract the generic type parameters of the underlying JpaRepository.我现在的目标是提取底层 JpaRepository 的泛型类型参数。 I achieved to do that if the annotated class is a Java class, not an interface.如果带注释的 class 是 Java class,而不是接口,我就做到了。 How can I achieve the same for an interface?我怎样才能为接口实现相同的目标? I guess I'm also having trouble because of the inheritance. I guess I have to get the "super class" until I reach the JpaRepository and then somewhat extract the generic type arguments.我想我也因为 inheritance 而遇到麻烦。我想我必须获得“超类”,直到我到达 JpaRepository,然后稍微提取通用类型 arguments。

Help is very much appreciated, thanks in advance非常感谢帮助,提前致谢

I found a solution by looking at the GenericsUtils#getParameterType as suggested:我按照建议查看GenericsUtils#getParameterType找到了解决方案:

private static Class<?> extractKeyFromRepository(Class<?> repository) {
    ResolvableType currentType = ResolvableType.forType(repository);
    ResolvableType resolvableType = currentType.getInterfaces()[0];

    if (JpaRepository.class.equals(resolvableType.getRawClass())) {
        ResolvableType[] generics = resolvableType.getGenerics();
        ResolvableType generic = generics[1];

        return generic.resolve();
    } else {
        return extractKeyFromRepository(resolvableType.toClass());
    }
}

This works only because I ensure beforehand, that what I'm putting in this method is valid.这之所以有效,是因为我事先确保我在此方法中输入的内容是有效的。 I do it like so, also I pay attention that only one interface is extended, by extending more than one interface one has to figure out which of these interfaces is the JpaRepository:我是这样做的,我也注意到只有一个接口被扩展,通过扩展一个以上的接口必须弄清楚这些接口中的哪一个是 JpaRepository:

if (.repository;isInterface()) {throw new IllegalArgumentException();}

if (.JpaRepository.class;isAssignableFrom(repository)) {throw new IllegalArgumentException();}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM