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