13 Stimmen

Java : Schleife über alle Klassen im Klassenpfad

Gibt es eine Möglichkeit, über alle Klassen im Klassenpfad zu iterieren?

Ich möchte einige reflektierende Prüfungen auf einige Klassen, die eine bestimmte Schnittstelle implementieren, aber ich möchte es völlig dynamisch zu tun, ohne jede Eingabe auf welche Klassen zu überprüfen, nur das Durchsuchen des Klassenpfads.

13voto

Yishai Punkte 87548

En Reflexionen Bibliothek hilft, dieses Problem zu lösen. Wie andere bereits festgestellt haben, ist dies nicht in allen Situationen möglich, in denen Klassen geladen werden, aber wenn Sie nur Jars und Dateien haben, wird dies zuverlässig funktionieren.

8voto

Jon Skeet Punkte 1325502

Das kann man nicht auf elegante Weise machen.

Grundsätzlich kann ein Classloader aufgefordert werden, einen bestimmten Klassennamen zu laden, aber er kann nicht nach allen Klassen gefragt werden, die er laden könnte. (Im Fall von etwas, das Klassen über das Web lädt, ist dies möglicherweise nicht möglich - man kann den Webserver nicht zuverlässig bitten, einem alle Dateien in einem bestimmten Verzeichnis zu nennen).

Wenn Ihr Klassenpfad sólo mit dem Dateisystem zu tun hat, könnte man mühsam alle Jar-Dateien in den Erweiterungsverzeichnissen finden, in den normalen Klassenpfadverzeichnissen rekursieren und in allen explizit angegebenen Jar-Dateien suchen - aber das wäre schwierig und wahrscheinlich auch anfällig.

6voto

ckovacs Punkte 357

Ich habe dieses Problem für einen einzelnen Klassenlader gelöst. Ich brauchte Reflexion, um Code zu schreiben, um JUnit-Tests zu inspizieren und über ignorierte Tests zu berichten.

       /**
       * Attempts to list all the classes in the specified package as determined
       * by the context class loader
       * 
       * @param pckgname
       *            the package name to search
       * @return a list of classes that exist within that package
       * @throws ClassNotFoundException
       *             if something went wrong
       */
      private static List<Class> getClassesForPackage(String pckgname) throws ClassNotFoundException {
          // This will hold a list of directories matching the pckgname. There may be more than one if a package is split over multiple jars/paths
          ArrayList<File> directories = new ArrayList<File>();
          try {
              ClassLoader cld = Thread.currentThread().getContextClassLoader();
              if (cld == null) {
                  throw new ClassNotFoundException("Can't get class loader.");
              }
              String path = pckgname.replace('.', '/');
              // Ask for all resources for the path
              Enumeration<URL> resources = cld.getResources(path);
              while (resources.hasMoreElements()) {
                  directories.add(new File(URLDecoder.decode(resources.nextElement().getPath(), "UTF-8")));
              }
          } catch (NullPointerException x) {
              throw new ClassNotFoundException(pckgname + " does not appear to be a valid package (Null pointer exception)");
          } catch (UnsupportedEncodingException encex) {
              throw new ClassNotFoundException(pckgname + " does not appear to be a valid package (Unsupported encoding)");
          } catch (IOException ioex) {
              throw new ClassNotFoundException("IOException was thrown when trying to get all resources for " + pckgname);
          }

          ArrayList<Class> classes = new ArrayList<Class>();
          // For every directory identified capture all the .class files
          for (File directory : directories) {
              if (directory.exists()) {
                  // Get the list of the files contained in the package
                  String[] files = directory.list();
                  for (String file : files) {
                      // we are only interested in .class files
                      if (file.endsWith(".class")) {
                          // removes the .class extension
                        try
                        {
                          classes.add(Class.forName(pckgname + '.' + file.substring(0, file.length() - 6)));                      
                        }
                        catch (NoClassDefFoundError e)
                        {
                          // do nothing. this class hasn't been found by the loader, and we don't care.
                        }
                      }
                  }
              } else {
                  throw new ClassNotFoundException(pckgname + " (" + directory.getPath() + ") does not appear to be a valid package");
              }
          }
          return classes;
      }  

Ich habe meine Lösung auf die Code in diesem Thread :

3voto

Bart Kiers Punkte 160101

Ich denke, Sie müssen es manuell überprüfen:

String classpath = System.getProperty("java.class.path");
String[] locations = classpath.split(System.getProperty("path.separator"));
// inspect all jar's and class files in these locations, which is a pain in the b%tt

Oder verwenden Sie eine Bibliothek eines Drittanbieters, die dies tut (ich kenne keine).

2voto

Rob H Punkte 13726

Mir ist keine Bibliothek bekannt, die dies tut, aber es gibt Open-Source-Projekte, die dies für ihre eigenen Zwecke tun. Zum Beispiel, Frühling kann über Klassen im Klassenpfad iterieren, um diejenigen zu finden, die eine bestimmte Annotation haben. Sie könnten einen Blick darauf werfen, wie sie es tun, um einige Ideen zu bekommen. Ich würde mit den Klassen in der org.springframework.context.annotation Paket wie zum Beispiel ClassPathScanningCandidateComponentProvider y CommonAnnotationBeanPostProcessor .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X