Qual é a melhor maneira de pesquisar em todo o caminho de classe por uma classe anotada?
Estou fazendo uma biblioteca e quero permitir que os usuários anotem suas classes, portanto, quando o aplicativo Web for iniciado, preciso varrer todo o caminho de classe para obter determinadas anotações.
Você conhece uma biblioteca ou uma instalação Java para fazer isso?
Edit: Estou pensando em algo como a nova funcionalidade para Java EE 5 Web Services ou EJB's. Você anota sua classe com @WebService
ou @EJB
e o sistema encontra essas classes durante o carregamento para que possam ser acessadas remotamente.
fonte
@Conditional
anotações. Portanto, se o@Conditional
valor de uma classe retornar false, ele não será retornadofindCandidateComponents
, mesmo que corresponda ao filtro do scanner. Isso me emocionou hoje - acabei usando a solução de Jonathan abaixo.BeanDefinition
objeto não fornece uma maneira de obter a classe diretamente. A coisa mais próxima parece ser agetBeanClassName
que retorna um nome de classe totalmente qualificado, mas o comportamento exato desse método não é claro. Além disso, não está claro em qual carregador de classes a classe foi encontrada.Class<?> cl = Class.forName(beanDef.getBeanClassName());
farenda.com/spring/find-annotated-classesE outra solução são as reflexões do Google .
Revisão rápida:
fonte
new Reflections("my.package").getTypesAnnotatedWith(MyAnnotation.class)
. c'est tout.Você pode encontrar classes com qualquer anotação no ClassGraph , bem como procurar outros critérios de interesse, por exemplo, classes que implementam uma determinada interface. (Isenção de responsabilidade, sou o autor do ClassGraph.) O ClassGraph pode criar uma representação abstrata de todo o gráfico da classe (todas as classes, anotações, métodos, parâmetros do método e campos) na memória, para todas as classes no caminho de classe ou para classes em pacotes na lista de permissões, e você pode consultar esse gráfico de classe da maneira que desejar. O ClassGraph suporta mais mecanismos de especificação de caminho de classe e carregadores de classe do que qualquer outro scanner, e também funciona perfeitamente com o novo sistema de módulo JPMS; portanto, se você basear seu código no ClassGraph, seu código será portátil no máximo. Veja a API aqui.
fonte
Reflections
. Além disso, se você estiver usando o goiaba / etc e quiser alterar as coleções, é fácil como torta. Grandes comentários dentro também.Se você quer uma solução realmente leve (sem dependências, API simples, arquivo jar de 15 kb) e uma solução muito rápida , dê uma olhada
annotation-detector
em https://github.com/rmuller/infomas-aslDisclaimer: Eu sou o autor.
fonte
É possível usar a API de processamento de anotação conectável do Java para gravar o processador de anotação que será executado durante o processo de compilação e coletará todas as classes anotadas e criará o arquivo de índice para uso em tempo de execução.
Essa é a maneira mais rápida possível de descobrir anotações de classe, porque você não precisa varrer seu caminho de classe em tempo de execução, o que geralmente é uma operação muito lenta. Além disso, essa abordagem funciona com qualquer carregador de classes e não apenas com URLClassLoaders geralmente suportados por scanners de tempo de execução.
O mecanismo acima já está implementado na biblioteca ClassIndex .
Para usá-lo, anote sua anotação personalizada com a meta-anotação @IndexAnnotated . Isso criará no momento da compilação um arquivo de índice: META-INF / anotações / com / test / YourCustomAnnotation listando todas as classes anotadas. Você pode acessar o índice em tempo de execução executando:
fonte
É tarde demais para responder. Eu diria que é melhor usar bibliotecas como ClassPathScanningCandidateComponentProvider ou como Scannotations
Mas, mesmo depois que alguém quer tentar trabalhar com o classLoader, escrevi alguns para imprimir as anotações das classes em um pacote:
E no arquivo de configuração, você coloca o nome do pacote e o desmarca em uma classe.
fonte
Com o Spring, você também pode escrever o seguinte usando a classe AnnotationUtils. ou seja:
Para obter mais detalhes e todos os métodos diferentes, consulte os documentos oficiais: https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/annotation/AnnotationUtils.html
fonte
null
valor como o segundo parâmetro (que define a classe, na qual a hierarquia de herança Spring procurará uma classe que use a Anotação), você sempre receberá umanull
resposta, de acordo com a implementação.Há um comentário maravilhoso do zapp que se encaixa em todas essas respostas:
fonte
A API do Classloader não possui um método "enumerar", porque o carregamento de classes é uma atividade "sob demanda" - você geralmente possui milhares de classes em seu caminho de classe, das quais apenas uma fração será necessária (o arquivo rt.jar hoje tem 48MB hoje!).
Portanto, mesmo se você pudesse enumerar todas as classes, isso consumiria muito tempo e memória.
A abordagem simples é listar as classes em questão em um arquivo de configuração (xml ou o que melhor lhe convier); se você quiser fazer isso automaticamente, restrinja-se a um diretório JAR ou a uma classe.
fonte
Google Reflection se você quiser descobrir interfaces também.
O Spring
ClassPathScanningCandidateComponentProvider
não está descobrindo interfaces.fonte
O Google Reflections parece ser muito mais rápido que o Spring. Encontrei esta solicitação de recurso que aborda essa diferença: http://www.opensaga.org/jira/browse/OS-738
Esse é um motivo para usar o Reflections, pois o tempo de inicialização do meu aplicativo é realmente importante durante o desenvolvimento. O Reflections também parece ser muito fácil de usar para o meu caso de uso (encontre todos os implementadores de uma interface).
fonte
Se você está procurando uma alternativa para reflexões , gostaria de recomendar o Panda Utilities - AnnotationsScanner . É um scanner livre de goiaba (goiaba tem ~ 3MB, Panda Utilities tem ~ 200kb) com base no código-fonte da biblioteca de reflexões.
Também é dedicado a pesquisas baseadas no futuro. Se você desejar varrer várias vezes as fontes incluídas ou fornecer uma API, que permita que alguém verifique o caminho de classe atual,
AnnotationsScannerProcess
armazena em cache todos osClassFiles
, por isso é muito rápido.Exemplo simples de
AnnotationsScanner
uso:fonte
A primavera tem algo chamado
AnnotatedTypeScanner
classe.Esta classe usa internamente
Esta classe possui o código para a verificação real dos recursos do caminho de classe . Isso é feito usando os metadados da classe disponíveis no tempo de execução.
Pode-se simplesmente estender essa classe ou usar a mesma classe para digitalização. Abaixo está a definição do construtor.
fonte