Размышления не могли получить тип класса

Поэтому я использую Java Reflections API для поиска в другой банке классов, которые расширяют 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

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

Заранее спасибо!

3 ответа

Решение

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

Так что вы можете попробовать что-то вроде следующего:

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

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

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

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

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

Сканирование для классов не просто с чистой 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}

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

Другие вопросы по тегам