Отражения не могут получить тип класса
Итак, я использую 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
}
Для получения дополнительной информации прочитайте ссылку