Отражения не могут получить тип класса

Итак, я использую API Java Reflections для поиска другого jar для классов, которые расширяют Foo, используя следующий код:

Reflections reflections = new Reflections("com.example");
for(Class<? extends Foo> e : reflections.getSubTypesOf(Foo.class)) {
    doSomething()
}

Когда я делаю это, Reflections выдает следующую ошибку:

org.reflections.ReflectionsException: could not get type for name com.example.ExtendsFoo

Кто-нибудь знает, как исправить эту причину, я озадачен?

Спасибо заранее!

Ответ 1

Проблема может быть связана с отсутствием загрузчика классов, который может разрешить имя (даже если он может разрешить подтип). Это звучит противоречиво, но у меня возникло сообщение об ошибке, когда я строил конфигурацию и использовал ClasspathHelper.forClassLoader для созданного приложением URLClassloader, чтобы выяснить, что сканировать на пути к классам, но не передавать в указанном URLClassLoader в конфигурацию Reflections, чтобы он может правильно создавать вещи.

Итак, вы можете попробовать что-то в следующих строках:

URLClassLoader urlcl = new URLClassLoader(urls);
Reflections reflections = new Reflections(
  new ConfigurationBuilder().setUrls(
    ClasspathHelper.forClassLoader(urlcl)
  ).addClassLoader(urlcl)
);

где urls - это массив URLS для банок, содержащих классы, которые вы хотите загрузить. Я получал ту же ошибку, что и вы, если бы у меня не было окончательного addClassLoader(...) вызова ConfigurationBuilder.

Если это не работает или не применимо, возможно, стоит просто установить точку останова в ReflectionsUtil.forName(String typeName, ClassLoader... classLoaders)), чтобы увидеть, что происходит.

Ответ 2

Посмотрите: https://code.google.com/p/reflections/issues/detail?id=163

Отражения (в текущей версии 0.9.9-RC1) не корректно перебрасывают исключение. Вот почему вы можете упустить истинную причину проблемы. В моем случае это был сломанный .class файл, который мой загрузчик класса по умолчанию не смог загрузить и выбросил исключение. Поэтому, прежде всего, постарайтесь убедиться, что ваш класс действительно загружен.

Ответ 3

Сканирование для классов непросто с чистой Java.

Структура spring предлагает класс ClassPathScanningCandidateComponentProvider, который может делать то, что вам нужно. В следующем примере будут найдены все подклассы MyClass в пакете org.example.package

ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(true);
 provider.addIncludeFilter(new AssignableTypeFilter(MyClass.class));

// scan in org.example.package
 Set<BeanDefinition> components = provider.findCandidateComponents("org/example/package");
for (BeanDefinition component : components)
{

Этот метод имеет дополнительное преимущество использования анализатора байт-кода для поиска кандидатов, что означает, что он не будет загружать все классы, которые он сканирует.   Класс cls = Class.forName(component.getBeanClassName());   // используем класс cls found }

Для получения дополнительной информации прочитайте ссылку