Как сканировать аннотации в Spring Web App с помощью библиотеки отражений (или другой)
У меня есть веб-приложение, созданное с помощью Spring и работающее внутри Jboss. Я пытаюсь во время выполнения сканировать классы с определенной аннотацией. Прямо сейчас я использую библиотеку Reflections с открытым исходным кодом
public static List<Class> scanForClassesWithAnnotation(Class<? extends Annotation> annotationClass)
{
List<Class> classesWithAnnotation = new ArrayList<>();
for(Package p : Package.getPackages())
{
LOGGER.info("scanForClassesWithAnnotation: Examining package " + p.getName());
try
{
List<ClassLoader> classLoadersList = new ArrayList<>();
classLoadersList.add(ClasspathHelper.contextClassLoader());
classLoadersList.add(ClasspathHelper.staticClassLoader());
Reflections reflections = new Reflections(
new ConfigurationBuilder()
.setScanners(new SubTypesScanner(false), new ResourcesScanner())
.setUrls(ClasspathHelper.forClassLoader(classLoadersList.toArray(new ClassLoader[classLoadersList.size()])))
.filterInputsBy(new FilterBuilder().include(FilterBuilder.prefix(p.getName()))));
Set<Class<?>> classes = reflections.getSubTypesOf(Object.class);
LOGGER.info("\tscanForClassesWithAnnotation: found classes " + JsonUtils.objectToJson(classes));
for(Class foundClass : classes)
{
if(foundClass.isAnnotationPresent(annotationClass))
{
classesWithAnnotation.add(foundClass);
}
}
} catch (Exception ignored) {}
}
return classesWithAnnotation;
}
Когда этот код выполняется, я вижу много таких сообщений в журнале:
given scan urls are empty. set urls in the configuration
Этот код работает в отдельном проекте Maven, поэтому я знаю, что он работает в целом. Но я думаю, что проблема в том, что код выполняется в контексте сервлета. Как это исправить? Как сканировать классы с аннотацией в веб-приложении Spring? Заранее спасибо.
2 ответа
Начните играть с
public class Scanner {
private static final Log log = LogFactory.getLog(Scanner.class);
public static void main(String[] args) throws IOException {
SimpleMetadataReaderFactory metadataFactory = new SimpleMetadataReaderFactory();
ResourcePatternResolver scaner = new PathMatchingResourcePatternResolver();
Resource[] resources = scaner.getResources("classpath*:/base.package/**/*.class");
for (Resource r : resources) {
log.info("Scanning [" + r.getDescription() + "]");
MetadataReader metadataReader = metadataFactory.getMetadataReader(r);
if (metadataReader.getAnnotationMetadata().isAnnotated("org.example.Annotation"))
log.info("found annotation in [" + r.getDescription() + "]");
}
}
Это работает
public static List<Class> scanForClassesWithAnnotation2(Class<? extends Annotation> annotationClass)
{
List<Class> classesWithAnnotation = new ArrayList<>();
ClassPathScanningCandidateComponentProvider scanner =
new ClassPathScanningCandidateComponentProvider(false);
scanner.addIncludeFilter(new AnnotationTypeFilter(annotationClass));
for (BeanDefinition bd : scanner.findCandidateComponents("com.example"))
{
try
{
classesWithAnnotation.add(Class.forName(bd.getBeanClassName()));
} catch (ClassNotFoundException e)
{
LOGGER.error("Could not create class from class name");
}
}
return classesWithAnnotation;
}