Java извлекать параметры типа c с отражением от интерфейса - PullRequest
0 голосов
/ 24 апреля 2020

Я пишу пользовательскую аннотацию Java для обработки CrudRepositories с отражением в Java Spring. С библиотекой org.reflections.reflections. Я получаю все интерфейсы, аннотированные моей аннотацией в виде файла класса, например:

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

Только интерфейсы, которые в какой-то момент расширяют JpaRepository, аннотируются мой @MyAnnotation на уровне класса.


Моя структура хранилища выглядит следующим образом: Есть два случая,

первый случай:
public interface SomeRepo extends JpaRepository<SomeEntity, Long> {...}

второй случай составлен из иерархии наследования:
public interface SuperClassRepo <T extends SomeRandomEntity> extends JpaRepository<T, String> {...}
public interface SubClassRepo extends SuperClassRepo<SubEntityOfSomeRandomEntity> {...}

Теперь моя цель - извлечь род c параметры типа базового JpaRepository. Я добился этого, если аннотированный класс - это класс Java, а не интерфейс. Как я могу добиться того же для интерфейса? Думаю, у меня тоже проблемы из-за наследства. Я думаю, мне нужно получить «суперкласс», пока я не достигну JpaRepository, а затем немного извлечь аргументы типа generi c.

Помощь очень ценится, заранее спасибо

1 Ответ

0 голосов
/ 24 апреля 2020

Я нашел решение, посмотрев на 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());
    }
}

Это работает только потому, что я заранее гарантирую, что то, что я помещаю в этот метод, действительный. Я делаю это так, также я обращаю внимание, что расширяется только один интерфейс, расширяя более одного интерфейса, нужно выяснить, какой из этих интерфейсов является JpaRepository:

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...