una sirve que poo para metodo interfaces implementacion herencia ejercicios ejemplo clases clase abstracto abstractas abstracta java java-ee quartz-scheduler
JavaClassFinder.zip

java - sirve - Encontrar todas las clases implementando una interfaz específica



metodo abstracto java (6)

Esta pregunta ya tiene una respuesta aquí:

Estoy en el proceso de desarrollar una aplicación (programador de Quartz) donde tenemos una clase de trabajo que es responsable de realmente ejecutar el trabajo y tenemos que decir / pasar el nombre de la clase de trabajo al crear un activador en el programador de Quartz.

Deseo proporcionar un punto de extensión para todos los que quieran usar la API (además de algunos trabajos genéricos que proporcionaré como parte de la API). La idea es crear una interfaz (marcador) y si alguien quiere declarar su clase como clase de trabajo del planificador, todo lo que tiene que hacer es, (declarar) implementar la interfaz.

No estoy seguro de cómo puedo encontrar qué clases siguen el contrato (implementando la interfaz) para poder mostrarlas al usuario que desea programar un desencadenador en el programador.

Mi requisito no es cargar las clases en tiempo de ejecución, sino mostrar la lista de usuarios de las clases que implementan la interfaz requerida para que el usuario pueda seleccionar la clase y el nombre de la clase se puede pasar al planificador. Es el programador de Quartz que al final será responsable de crear una instancia de clase.

¿Puede alguien sugerir cómo puedo lograr el objetivo anterior o hay alguna otra forma mejor de lograr lo que estoy tratando de hacer?

Editar

ServiceLoader el documento de ServiceLoader y parece que para implementar un servicio uno tiene que crear un archivo en la carpeta META-INF con el nombre de la clase de implementación, lo que me lleva a pensar que si el usuario de mi API quiere 20 diferentes implementaciones, tiene que poner 20 entradas en el archivo que para mí parece mucho trabajo adicional para el usuario final ya que cada clase de trabajo se creará para ejecutar un trabajo específico y puede haber cientos de clases de trabajo.

Por favor corrígeme si mi suposición es incorrecta.


Creo que org.reflections es una solución adecuada, como menciona Alex Stybaev, no es necesario que haga referencia a las clases en un archivo de propiedades.

Otro enfoque (que tomaría) es Spring , ya que estoy usando Spring de todos modos para mis aplicaciones y, por lo tanto, no necesitaría ninguna dependencia adicional.

Puede encontrar sugerencias para resolver su problema con Spring (y alternativas en los otros comentarios o respuestas) aquí:

En los comentarios de tu pregunta, heikkim y polypiel también vinculan a las preguntas con respuestas para resolverlo con Spring:

  • https://.com/a/8166959/734687
  • https://.com/a/1415338/734687


Para hacerlo en Java puro, la respuesta más correcta ya ha sido votada (de sam goldberg apr 10,2012)

Sin embargo, el código completo de él es innecesariamente complejo. Usé su idea y empujé ClassFinder allí: http://icedtea.classpath.org/hg/icedtea-web/file/0527ad4eb2dd/netx/net/sourceforge/jnlp/controlpanel/ClassFinder.java

Nota: esto funcionará en una aplicación independiente (o cualquier aplicación que utilice classpath regular con jar y dir), no en ServerContainer.

si su aplicación se ejecuta en un servidor web, necesita saber la ubicación de su guerra / oído y buscar allí. O tiene que preguntarle a su padre o madre de la clase dónde está obteniendo la suya (y otras) fuentes.

Segunda nota: estoy filtrando las clases de ubicaciones finales para que coincidan solo con netx e icedtea-web ya que no deseo que se busquen las dependencias. Entonces, si necesita incluir rt.jar por favor, rmeove thsoe filters. O elimine bootclasspath si no lo necesita en absoluto.


Probablemente la mejor manera (estándar) de hacer esto utilizando el mecanismo de Java SPI, vea ServiceLoader . El inconveniente (que también es una buena característica) es que espera que los Jars que definen las extensiones los META-INF/services/your.fully.qualified.Interface en META-INF/services/your.fully.qualified.Interface .

La única otra forma en que puedo pensar sería recorrer todos los ClassLoaders con la esperanza de que puedas enumerar los archivos allí, cargar los archivos de clase y ver si implementan tu interfaz o no, lo cual no es nada agradable. que hacer.


Puedes encontrar una respuesta here .

Puedo sugerir el uso de org.reflections

ingrese la descripción del enlace aquí

Reflections reflections = new Reflections("com.mycompany"); Set<Class<? extends MyInterface>> classes = reflections.getSubTypesOf(MyInterface.class);


Tenía una necesidad similar en la que quería asegurarme de que las clases creadas que implementaban cierta interfaz siempre fueran realmente serializables. Creé un JavaClassFinder que recorre todos los directorios en el classpath y encuentra todas las clases asignables a la interfaz que me importaba. Aquí hay un fragmento de código:

public <T> List<Class<? extends T>> findAllMatchingTypes(Class<T> toFind) { foundClasses = new ArrayList<Class<?>>(); List<Class<? extends T>> returnedClasses = new ArrayList<Class<? extends T>>(); this.toFind = toFind; walkClassPath(); for (Class<?> clazz : foundClasses) { returnedClasses.add((Class<? extends T>) clazz); } return returnedClasses; }

Me complace compartir el código con usted si ayuda. El único inconveniente es que esto solo manejará archivos .class - No agregué la función para descomprimir .jars y leer archivos de clase desde allí. (Pero no sería un gran proyecto agregar eso).

ACTUALIZACIÓN: Revisé mi código fuente para el anterior, y encontré que depende de muchas clases de ayuda en nuestra biblioteca de utilidad estándar. Para hacerlo más fácil, compruebo todo el código necesario, que puedes descargar de JavaClassFinder.zip . Esto se configurará directamente en Eclipse, y puede tomar las partes del código que necesite.

Encontrará una prueba JUnit3 en el proyecto, llamada JavaClassFinderTest.java, que le muestra las características y el uso de la clase JavaClassFinder. La única dependencia externa necesaria para ejecutar la prueba de Junit es Junit.

Uso básico de esta utilidad:

JavaClassFinder classFinder = new JavaClassFinder(); List<Class<? extends MyTagInterface>> classes = classFinder.findAllMatchingTypes(MyTagInterface.class);

Esto le dará una lista que contiene cualquier clase en el classpath que se puede asignar desde "MyTagInterface.class" (por ejemplo). Espero que esto ayude.