¿Cómo encontrar métodos anotados en un paquete dado?

Tengo una anotación de marcador simple para los métodos (similar al primer ejemplo en el Ítem 35 en Effective Java (2nd ed)):

/** * Marker annotation for methods that are called from installer's * validation scripts etc. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface InstallerMethod { } 

Luego, en un paquete dado (digamos com.acme.installer ), que tiene algunos subpaquetes que contienen unas 20 clases, me gustaría encontrar todos los métodos que están anotados con él. (Porque me gustaría hacer algunos controles con respecto a todos los métodos anotados en una prueba unitaria).

¿Qué (si hay alguno) es la forma más fácil de hacer esto? Preferiblemente sin agregar nuevas bibliotecas o marcos de terceros.

Editar : para aclarar, obviamente method.isAnnotationPresent(InstallerMethod.class) será la forma de verificar si un método tiene la anotación, pero este problema incluye encontrar todos los métodos.

Si quiere implementarlo usted mismo, estos métodos encontrarán todas las clases en un paquete dado:

 /** * Scans all classes accessible from the context class loader which belong * to the given package and subpackages. * * @param packageName * The base package * @return The classes * @throws ClassNotFoundException * @throws IOException */ private Iterable getClasses(String packageName) throws ClassNotFoundException, IOException { ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); String path = packageName.replace('.', '/'); Enumeration resources = classLoader.getResources(path); List dirs = new ArrayList(); while (resources.hasMoreElements()) { URL resource = resources.nextElement(); URI uri = new URI(resource.toString()); dirs.add(new File(uri.getPath())); } List classes = new ArrayList(); for (File directory : dirs) { classes.addAll(findClasses(directory, packageName)); } return classes; } /** * Recursive method used to find all classes in a given directory and * subdirs. * * @param directory * The base directory * @param packageName * The package name for classes found inside the base directory * @return The classes * @throws ClassNotFoundException */ private List findClasses(File directory, String packageName) throws ClassNotFoundException { List classes = new ArrayList(); if (!directory.exists()) { return classes; } File[] files = directory.listFiles(); for (File file : files) { if (file.isDirectory()) { classes.addAll(findClasses(file, packageName + "." + file.getName())); } else if (file.getName().endsWith(".class")) { classes.add(Class.forName(packageName + '.' + file.getName().substring(0, file.getName().length() - 6))); } } return classes; } 

Luego puedes filtrar esas clases con la anotación dada:

 for (Method method : testClass.getMethods()) { if (method.isAnnotationPresent(InstallerMethod.class)) { // do something } } 

Probablemente deberías echarle un vistazo a la biblioteca Reflections de código abierto. Con él puedes lograr fácilmente lo que quieras con pocas líneas de código:

 Reflections reflections = new Reflections( new ConfigurationBuilder().setUrls( ClasspathHelper.forPackage( "com.acme.installer" ) ).setScanners( new MethodAnnotationsScanner() ) ); Set methods = reflections.getMethodsAnnotatedWith(InstallerMethod.class); 

Si está contento de usar Spring, eso hace algo en esta línea usando su contexto: funcionalidad de exploración de componentes, donde Spring escanea para clases anotadas en un paquete dado. Debajo de las portadas, es bastante horrible, e implica hurgar en el sistema de archivos y en los archivos JAR buscando clases en el paquete.

Incluso si no puede usar Spring directamente, echarle un vistazo a su código fuente puede darle algunas ideas.

Ciertamente, la APi de reflexión de Java no sirve para nada, específicamente no proporciona un medio para obtener todas las clases en un paquete.