implementacion - interfaces en java ejemplos
¿Cómo puedo obtener una lista de todas las implementaciones de una interfaz mediante programación en Java? (8)
Además, si está escribiendo un complemento IDE (donde lo que intenta hacer es relativamente común), entonces el IDE generalmente le ofrece formas más eficientes de acceder a la jerarquía de clases del estado actual del código de usuario.
¿Puedo hacerlo con reflejo o algo así?
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, deberá implementar su propio analizador de archivos de clase que opera de manera más eficiente, en lugar de la reflexión. Una biblioteca de ingeniería de código de bytes puede ayudar con este enfoque.
El mecanismo del proveedor de servicios 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é un ejemplo en otra respuesta.
He estado buscando por un tiempo y parece que hay diferentes enfoques, aquí hay un resumen:
Reflections biblioteca de Reflections 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 la respuesta de erickson) y 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, debe definir
Pet
como ServiceProviderInterface (SPI) y declarar sus implementaciones. lo puedes hacer creando un archivo enresources/META-INF/services
con el nombreexamples.reflections.Pet
y declarar todas las implementaciones dePet
en élexamples.reflections.Dog examples.reflections.Cat
anotación a nivel de paquete . Aquí hay 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 la 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í hay contenido de muestra:@MyPackageAnnotation(implementationsOfPet = {Dog.class, Cat.class}) package examples.reflections;
Tenga en cuenta que solo los paquetes que conoce el ClassLoader en ese momento se cargarán mediante una llamada a
Package.getPackages()
.
Además, hay otros enfoques basados en URLClassLoader que siempre estarán limitados a las clases que ya se han cargado, a menos que realice una búsqueda basada en el directorio.
Lo que dijo Erickson, pero si aún quieres hacerlo, echa un vistazo a Reflections . De su página:
Con Reflections puede consultar sus metadatos para:
- obtener todos los subtipos de algún tipo
- obtener todos los tipos anotados con alguna anotación
- obtener todos los tipos anotados con alguna anotación, incluidos los parámetros de anotación que coincidan
- obtener todos los métodos anotados con algunos
Lo que dijo Ericson es lo mejor. Aquí hay un hilo de preguntas y respuestas relacionadas: 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/
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.
Sí, el primer paso es identificar "todas" las clases que te 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
Spring tiene una forma bastante simple de lograr esto:
public interface ITask {
void doStuff();
}
@Component
public class MyTask implements ITask {
public void doStuff(){}
}
Luego puede conectar automáticamente una lista de tipo ITask
y Spring la rellenará con todas las implementaciones:
@Service
public class TaskService {
@Autowired
private List<ITask> tasks;
}