¿Puedo hacerlo con reflejo o algo así?¿Cómo puedo obtener una lista de todas las implementaciones de una interfaz mediante programación en Java?
Respuesta
Sí, el primer paso es identificar "todas" las clases que le interesan. Si ya tiene esta información, puede enumerarla a través de cada uno de ellos y usar instanceof para validar la relación. Un artículo relacionado está aquí: http://www.javaworld.com/javaworld/javatips/jw-javatip113.html
Además, si está escribiendo un complemento IDE (donde lo que está tratando de hacer es relativamente común), entonces el IDE generalmente le ofrece formas más eficientes de acceder a la jerarquía de clases de la corriente estado del código de usuario.
En general, es costoso hacer esto. Para usar la reflexión, la clase debe estar cargada. Si desea cargar todas las clases disponibles en el classpath, eso llevará tiempo y memoria, y no es recomendable.
Si desea evitar esto, tendrá que implementar su propio analizador de archivos de clase que opera de manera más eficiente, en lugar de reflexión. Una biblioteca de ingeniería de código de bytes puede ayudar con este enfoque.
El Service Provider mechanism es el medio convencional para enumerar las implementaciones de un servicio conectable. Use el ServiceLoader
en Java 6 o implemente el suyo en versiones anteriores. Proporcioné an example en otra respuesta.
Desafortunadamente, el mecanismo del Proveedor de servicios requiere que liste las clases que podrían estar en la lista de interés en un archivo separado que a menudo es inviable. – averasko
Es factible escribir código fuente implementando una interfaz, compilarla e implementarla, pero ¿no es factible incluir un archivo de texto con la FQN de la implementación? Rara vez, si es que alguna vez, el caso. Apenas "a menudo". – erickson
Lo que dijo erickson, pero si aún desea hacerlo, eche un vistazo a Reflections. Desde su página:
Usando Reflexiones puede consultar los metadatos para:
- obtener todos los subtipos de algún tipo
- obtener todo tipo anotados con alguna anotación
- obtener todos los tipos anotado con algunos anotación, incluidos los parámetros de anotación que coinciden con
- obtener todos los métodos anotados con algunos
más específico: 'new Reflections (" my.package "). GetSubTypesOf (MyInterface.class)' – zapp
Lo que dijo erikson es lo mejor. Aquí hay un hilo relacionado de preguntas y respuestas: http://www.velocityreviews.com/forums/t137693-find-all-implementing-classes-in-classpath.html
La biblioteca Apache BCEL le permite leer clases sin cargarlas. Creo que será más rápido porque debería poder omitir el paso de verificación. El otro problema con la carga de todas las clases con el cargador de clases es que sufrirá un gran impacto en la memoria y ejecutará inadvertidamente cualquier bloque de código estático que probablemente no desee.
El enlace de la biblioteca Apache BCEL - http://jakarta.apache.org/bcel/
He estado buscando por un tiempo y parece que hay diferentes enfoques, aquí está un resumen:
reflections biblioteca es bastante popular si no te importa agregar la dependencia.Se vería así:
Reflections reflections = new Reflections("firstdeveloper.examples.reflections"); Set<Class<? extends Pet>> classes = reflections.getSubTypesOf(Pet.class);
ServiceLoader (según respuesta Erickson) y que se vería así:
ServiceLoader<Pet> loader = ServiceLoader.load(Pet.class); for (Pet implClass : loader) { System.out.println(implClass.getClass().getSimpleName()); // prints Dog, Cat }
Tenga en cuenta que para que esto funcione es necesario definir
Pet
como ServiceProviderInterface (SPI) y declare sus implementaciones. lo hace mediante la creación de un archivo enresources/META-INF/services
con el nombreexamples.reflections.Pet
y declarar todas las implementaciones dePet
en ellaexamples.reflections.Dog examples.reflections.Cat
anotación de nivel de paquete de. He aquí un ejemplo:
Package[] packages = Package.getPackages(); for (Package p : packages) { MyPackageAnnotation annotation = p.getAnnotation(MyPackageAnnotation.class); if (annotation != null) { Class<?>[] implementations = annotation.implementationsOfPet(); for (Class<?> impl : implementations) { System.out.println(impl.getSimpleName()); } } }
y la definición de anotación:
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PACKAGE) public @interface MyPackageAnnotation { Class<?>[] implementationsOfPet() default {}; }
y debe declarar la anotación a nivel de paquete en un archivo llamado
package-info.java
dentro de ese paquete. aquí están los contenidos de la muestra:@MyPackageAnnotation(implementationsOfPet = {Dog.class, Cat.class}) package examples.reflections;
Tenga en cuenta que sólo los paquetes que se sabe que el cargador de clases en ese momento se cargarán por una llamada a
Package.getPackages()
.
Además, existen otros enfoques basados en URLClassLoader que siempre será limitada a las clases que han sido ya cargados, menos que hace una búsqueda basada en el directorio.
¿Cuál de los tres enfoques es más eficiente y más rápido? – carlspring
@carlspring No puedo hacer una declaración absoluta acerca de su eficiencia relativa, pero la primera alternativa (biblioteca de reflexiones) funcionó bastante bien para mí. –
Me encontré con el mismo problema. Mi solución fue utilizar la reflexión para examinar todos los métodos en una clase ObjectFactory, eliminando aquellos que no eran métodos createXXX() que devolvían una instancia de uno de mis POJO enlazados. Cada clase así descubierta se agrega a una matriz Class [], que luego se pasó a la llamada de creación de instancias de JAXBContext. Esto funciona bien, solo necesita cargar la clase ObjectFactory, que de todos modos iba a necesitarse. Solo necesito mantener la clase ObjectFactory, una tarea realizada a mano (en mi caso, porque comencé con POJO y usé schemagen), o puede ser generada cuando sea necesario por xjc. De cualquier forma, es perfecto, simple y efectivo.
primavera tiene una forma bastante sencilla de lograr esto:
public interface ITask {
void doStuff();
}
@Component
public class MyTask implements ITask {
public void doStuff();
}
A continuación, puede Autowire una lista de tipo ITask
y la primavera se rellenará con todas las implementaciones:
@Service
public class TaskService {
@Autowired
private List<ITask> tasks;
}
- 1. ¿Cómo puedo obtener las propiedades del sistema para una instancia de JVM en particular mediante programación?
- 2. ServiceLoader encontrar implementaciones de una interfaz
- 3. ¿Cómo puedo obtener la latitud, longitud de una ubicación mediante programación o mediante una API
- 4. Obtener una lista de todas las sesiones activas en ASP.NET
- 5. Cómo obtener mediante programación una lista de colores de un degradado en Android
- 6. Windows: ¿cómo obtener una lista de todas las ventanas visibles?
- 7. ¿Reflejando todas las propiedades de una interfaz, incluidas las heredadas?
- 8. ¿Puedo usar StructureMap para devolver todas las implementaciones de una interfaz genérica para un parámetro de tipo específico
- 9. la inyección de un Enumerable que contiene todas las implementaciones registradas de una interfaz
- 10. ¿Cómo obtener una lista de todas las NSWindow abiertas desde todas las aplicaciones en ejecución?
- 11. Obtener una lista de todas las etiquetas únicas en mongodb
- 12. ¿Cómo puedo recopilar una lista de todas mis aplicaciones de iOS mediante programación a través de Internet?
- 13. ¿Cómo puedo obtener una lista de todas las variables definidas en Matlab u Octave?
- 14. ¿Cómo puedo obtener una lista de todas las canalizaciones con nombre abierto en Windows?
- 15. ¿Cómo puedo seleccionar mediante programación una subtrama específica en Matplotlib?
- 16. ¿Cómo puedo obtener una lista de todas las propiedades de un ABRecordRef?
- 17. ¿Cómo obtener velocidad de enlace mediante programación?
- 18. ¿Es posible obtener todas las subclases de una clase?
- 19. ¿Cómo puedo detectar el fondo de una imagen mediante programación?
- 20. En Java, ¿cómo iterar en las constantes de una interfaz?
- 21. Interfaz de lista: de Java a C#
- 22. ¿Cómo puedo obtener todas las permutaciones posibles de una lista con Common Lisp?
- 23. ¿Cómo puedo obtener una lista de todas las almohadillas Etherpad-lite
- 24. Obtener lista de todas las aplicaciones instaladas
- 25. En Linux: ¿cómo puedo determinar mediante programación si una interfaz NIC está habilitada y conectada?
- 26. ¿Cómo puedo posicionar una vista mediante programación usando puntos relativos?
- 27. ¿Cómo puedo restablecer un NSSearchField de cacao mediante programación?
- 28. ¿Cómo puedo probar mediante programación una conexión HTTP?
- 29. ¿Cómo obtener todas las palabras de una cadena en C#?
- 30. ¿Cómo puedo cambiar la fuente de una etiqueta mediante programación?
¿Es posible hacer con algún atajo mágico de Eclipse? ? –