ejemplo crear anotaciones annotation java annotations classloader

anotaciones - crear annotation en java



Escaneando anotaciones de Java en tiempo de ejecuciĆ³n (17)

¿Es demasiado tarde para responder? Yo diría que es mejor ir por bibliotecas como ClassPathScanningCandidateComponentProvider o como Scannotation

Pero incluso después de que alguien quiera probarlo con classLoader, he escrito algunos por mi cuenta para imprimir las anotaciones de las clases en un paquete:

public class ElementScanner { public void scanElements(){ try { //Get the package name from configuration file String packageName = readConfig(); //Load the classLoader which loads this class. ClassLoader classLoader = getClass().getClassLoader(); //Change the package structure to directory structure String packagePath = packageName.replace(''.'', ''/''); URL urls = classLoader.getResource(packagePath); //Get all the class files in the specified URL Path. File folder = new File(urls.getPath()); File[] classes = folder.listFiles(); int size = classes.length; List<Class<?>> classList = new ArrayList<Class<?>>(); for(int i=0;i<size;i++){ int index = classes[i].getName().indexOf("."); String className = classes[i].getName().substring(0, index); String classNamePath = packageName+"."+className; Class<?> repoClass; repoClass = Class.forName(classNamePath); Annotation[] annotations = repoClass.getAnnotations(); for(int j =0;j<annotations.length;j++){ System.out.println("Annotation in class "+repoClass.getName()+ " is "+annotations[j].annotationType().getName()); } classList.add(repoClass); } } catch (ClassNotFoundException e) { e.printStackTrace(); } } /** * Unmarshall the configuration file * @return */ public String readConfig(){ try{ URL url = getClass().getClassLoader().getResource("WEB-INF/config.xml"); JAXBContext jContext = JAXBContext.newInstance(RepositoryConfig.class); Unmarshaller um = jContext.createUnmarshaller(); RepositoryConfig rc = (RepositoryConfig) um.unmarshal(new File(url.getFile())); return rc.getRepository().getPackageName(); }catch(Exception e){ e.printStackTrace(); } return null; } }

Y en el archivo de configuración, pones el nombre del paquete y lo eliminas a una clase.

¿Cuál es la mejor manera de buscar el classpath completo para una clase anotada?

Estoy haciendo una biblioteca y quiero permitir que los usuarios anoten sus clases, así que cuando la aplicación web se inicie, necesito escanear toda la ruta de clase para una anotación determinada.

¿Conoces una biblioteca o una instalación de Java para hacer esto?

Edición: Estoy pensando en algo como la nueva funcionalidad para Java EE 5 Web Services o EJB''s. @WebService tu clase con @WebService o @EJB y el sistema encuentra estas clases mientras se cargan para que sean accesibles de forma remota.




Google Reflections parece ser mucho más rápido que Spring. Encontré esta solicitud de función que aborda esta diferencia: http://www.opensaga.org/jira/browse/OS-738

Esta es una razón para usar Reflections, ya que el tiempo de inicio de mi aplicación es realmente importante durante el desarrollo. Las reflexiones también parecen ser muy fáciles de usar para mi caso de uso (encontrar todos los implementadores de una interfaz).


Java no tiene "Discovery". La única forma que conozco es escanear el directorio en el que deberían estar los archivos .class, analizar los nombres y usarlos. Horriblemente feo, tal vez haya un paquete mejor en estos días, no lo he visto en algunos años.

Por lo general, este problema solía resolverse al incluir un archivo de propiedades o un archivo .xml con los nombres de clase en él.

También me interesaría escuchar una mejor respuesta.


La API del Cargador de clases no tiene un método de "enumeración", porque la carga de clases es una actividad "a pedido". Por lo general, tiene miles de clases en su ruta de clase, solo una fracción de las cuales será necesaria (rt.jar solo es 48MB hoy en día!).

Entonces, incluso si pudieras enumerar todas las clases, esto consumiría mucho tiempo y memoria.

El enfoque simple es enumerar las clases en cuestión en un archivo de configuración (xml o lo que sea más conveniente para usted); Si desea hacer esto automáticamente, limítese a un JAR o un directorio de clase.


No estoy seguro de si te ayudará o no, pero podrías ver el proyecto de descubrimiento de apache commons.

proyecto de descubrimiento


Puede encontrar clases con cualquier anotación dada con ClassGraph , así como buscar otros criterios de interés, por ejemplo, clases que implementan una interfaz determinada. (Descargo de responsabilidad, soy el autor de ClassGraph). ClassGraph puede generar una representación abstracta de la clase completa (todas las clases, anotaciones, métodos, parámetros de método y campos) en la memoria, para todas las clases en el classpath o para las clases en en la lista blanca, y puede consultar ese gráfico de clase como lo desee. ClassGraph admite más mecanismos de especificación de ruta de clase y cargadores de clases que cualquier otro escáner, y también funciona a la perfección con el nuevo sistema de módulos JPMS, por lo que si basa su código en ClassGraph, su código será portátil. Vea la API aquí.


Puede usar la Java Pluggable Annotation Processing API para escribir el procesador de anotaciones que se ejecutará durante el proceso de compilación y recopilará todas las clases anotadas y creará el archivo de índice para uso en tiempo de ejecución.

Esta es la forma más rápida posible de realizar el descubrimiento de clases anotadas porque no necesita escanear su classpath en tiempo de ejecución, lo que generalmente es una operación muy lenta. Además, este enfoque funciona con cualquier cargador de clases y no solo con URLClassLoaders generalmente soportados por escáneres de tiempo de ejecución.

El mecanismo anterior ya está implementado en la biblioteca ClassIndex .

Para usarlo, anote su anotación personalizada con @IndexAnnotated meta-anotación. Esto creará en el momento de la compilación un archivo de índice: META-INF / annotations / com / test / YourCustomAnnotation que enumera todas las clases anotadas. Puede acceder al índice en tiempo de ejecución ejecutando:

ClassIndex.getAnnotated(com.test.YourCustomAnnotation.class)


Si desea un peso realmente ligero (sin dependencias, API simple, archivo jar de 15 kb) y una solución muy rápida , eche un vistazo al annotation-detector encuentra en https://github.com/rmuller/infomas-asl

Descargo de responsabilidad: yo soy el autor.



Si está buscando una alternativa a las reflexiones, me gustaría recomendar Panda Utilities - AnnotationsScanner . Es un escáner sin guayaba (Guava tiene ~ 3MB, Panda Utilities tiene ~ 200kb) basado en el código fuente de la biblioteca de reflexiones.

También se dedica a búsquedas basadas en el futuro. Si desea escanear varias veces las fuentes incluidas o incluso proporcionar una API, lo que permite a alguien escanear la ruta de ClassFiles actual, AnnotationsScannerProcess almacena en caché todos los ClassFiles obtenidos, por lo que es realmente rápido.

Ejemplo simple del uso de AnnotationsScanner :

AnnotationsScanner scanner = AnnotationsScanner.createScanner() .includeSources(ExampleApplication.class) .build(); AnnotationsScannerProcess process = scanner.createWorker() .addDefaultProjectFilters("net.dzikoysk") .fetch(); Set<Class<?>> classes = process.createSelector() .selectTypesAnnotatedWith(AnnotationTest.class);


Trate de Scannotation .

Se puede utilizar para buscar anotaciones específicas en el classpath o en su directorio de aplicaciones web.


Un poco fuera de lugar, pero Spring también hace algo similar, usando <context:component-scan> , del cual quizás podrías estudiar el código fuente de?

Spring proporciona la capacidad de detectar automáticamente clases "estereotipadas" [...]. Para autodetectar estas clases y registrar los beans correspondientes se requiere la inclusión del [contexto: componente-elemento de escaneo].


Use el ServiceLoader o implemente el suyo propio si no está en Java 6.

Tal vez un procesador de anotaciones podría producir los archivos necesarios bajo META-INF / services en tiempo de compilación.


Utilice org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider

API

Un proveedor de componentes que escanea el classpath desde un paquete base. Luego aplica excluir e incluir filtros a las clases resultantes para encontrar candidatos.

ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(<DO_YOU_WANT_TO_USE_DEFALT_FILTER>); scanner.addIncludeFilter(new AnnotationTypeFilter(<TYPE_YOUR_ANNOTATION_HERE>.class)); for (BeanDefinition bd : scanner.findCandidateComponents(<TYPE_YOUR_BASE_PACKAGE_HERE>)) System.out.println(bd.getBeanClassName());


Y otra solución es reflexiones de Google .

Revisión rápida:

  • La solución Spring es el camino a seguir si está utilizando Spring. De lo contrario es una gran dependencia.
  • Usar ASM directamente es un poco engorroso.
  • Usar Java Assist directamente es demasiado pesado también.
  • Annovention es super ligero y conveniente. No hay integración de maven todavía.
  • Las reflexiones de Google atraen a las colecciones de Google. Indexa todo y luego es super rapido.