2010-07-11 2 views

답변

44

빈 경로 StringClassLoader#getResources()에 전달하여 모든 classpath 루트를 가져올 수 있습니다.

Enumeration<URL> roots = classLoader.getResources(""); 

당신이 만들 수있는 File 다음과 같이 URL에 따라 :

for (File file : root.listFiles()) { 
    // ... 
} 

당신은 할 수 있습니다

File root = new File(url.getPath()); 

당신은 주어진 디렉토리에있는 모든 파일의 목록을 얻을 수 File#listFiles()을 사용할 수 있습니다 표준 java.io.File 메서드를 사용하여 디렉토리인지 확인하고 파일 이름을 가져 오십시오.

if (file.isDirectory()) { 
    // Loop through its listFiles() recursively. 
} else { 
    String name = file.getName(); 
    // Check if it's a .class file or a .jar file and handle accordingly. 
} 

는 유일한 기능 요구 사항에 따라, 나는 Reflections library 훨씬 더 정확하게 당신이 원하는 것을 생각한다.

+0

"? 'classLoader.getResources ("")'는 classpath에 하나 또는 두 개의 디렉토리 만 반환한다는 것을 알게되었습니다. 자신이 작성한 .class 파일을 포함하는 것 (타사 패키지의 파일이 아닌)을 반환합니다. – flow2k

+0

그리고 classpath의 전체 목록을 원한다면'URL [] urls = ((URLClassLoader) classLoader) .getURLs()'를 사용하지 않아야합니까? – flow2k

0

나는 종종 이것을 찾습니다. 클래스 패스에서 모든 것을 찾을지라도 주어진 클래스 로더가 사용할 수있는 모든 것을 찾을 수는 없기 때문에 (예를 들어 DB에서 클래스 정의를 한 번 직접로드 한 프로젝트에서 작업 한 경우) 어려울 수 있습니다.

이 시점에서 가장 좋은 방법은 아마도 Spring을 살펴 보는 것일 것입니다. 클래스 패스의 클래스를 검색하여 킥 스타트에 필요한 주석이 있는지 확인합니다.

Scanning Java annotations at runtime

13

가 여기에 내가 그것을 할 쓴 내용은 다음과 같습니다

여기 허용 대답은 시작하기에 좋은 장소입니다. classpath와 함께 이상한 일을한다면 모든 것을 얻지 못할 것이라고 확신하지만, 그것은 나에게 잘 작동하는 것 같습니다. 실제로 클래스를로드하지는 않으며 이름을 반환한다는 점에 유의하십시오.

ClassFinder.findClasses(new Visitor<String>() { 
    @Override 
    public boolean visit(String clazz) { 
     System.out.println(clazz) 
     return true; // return false if you don't want to see any more classes 
    } 
}); 
: 그것은 메모리에 모든 클래스를로드하지 않도록하고, 잘못된 시간에로드 된 경우 내 회사의 코드베이스의 일부 클래스가 초기화 오류가 발생했기 때문에이

public interface Visitor<T> { 
    /** 
    * @return {@code true} if the algorithm should visit more results, 
    * {@code false} if it should terminate now. 
    */ 
    public boolean visit(T t); 
} 

public class ClassFinder { 
    public static void findClasses(Visitor<String> visitor) { 
     String classpath = System.getProperty("java.class.path"); 
     String[] paths = classpath.split(System.getProperty("path.separator")); 

     String javaHome = System.getProperty("java.home"); 
     File file = new File(javaHome + File.separator + "lib"); 
     if (file.exists()) { 
      findClasses(file, file, true, visitor); 
     } 

     for (String path : paths) { 
      file = new File(path); 
      if (file.exists()) { 
       findClasses(file, file, false, visitor); 
      } 
     } 
    } 

    private static boolean findClasses(File root, File file, boolean includeJars, Visitor<String> visitor) { 
     if (file.isDirectory()) { 
      for (File child : file.listFiles()) { 
       if (!findClasses(root, child, includeJars, visitor)) { 
        return false; 
       } 
      } 
     } else { 
      if (file.getName().toLowerCase().endsWith(".jar") && includeJars) { 
       JarFile jar = null; 
       try { 
        jar = new JarFile(file); 
       } catch (Exception ex) { 

       } 
       if (jar != null) { 
        Enumeration<JarEntry> entries = jar.entries(); 
        while (entries.hasMoreElements()) { 
         JarEntry entry = entries.nextElement(); 
         String name = entry.getName(); 
         int extIndex = name.lastIndexOf(".class"); 
         if (extIndex > 0) { 
          if (!visitor.visit(name.substring(0, extIndex).replace("/", "."))) { 
           return false; 
          } 
         } 
        } 
       } 
      } 
      else if (file.getName().toLowerCase().endsWith(".class")) { 
       if (!visitor.visit(createClassName(root, file))) { 
        return false; 
       } 
      } 
     } 

     return true; 
    } 

    private static String createClassName(File root, File file) { 
     StringBuffer sb = new StringBuffer(); 
     String fileName = file.getName(); 
     sb.append(fileName.substring(0, fileName.lastIndexOf(".class"))); 
     file = file.getParentFile(); 
     while (file != null && !file.equals(root)) { 
      sb.insert(0, '.').insert(0, file.getName()); 
      file = file.getParentFile(); 
     } 
     return sb.toString(); 
    } 
} 

를 사용하려면 ...입니다

+2

String [] paths = classpath.split (System.getProperty ("path.separator"));를 사용해야합니다. 그렇지 않으면 리눅스에서 작동하지 않을 것입니다 – sherif

+0

@sherif, 감사합니다! – Andy

+0

나는 이것을 시험해보고 싶다. ClassFinder를 사용할 코드를 보여줄 수 있습니까? –

7

Guava 라이브러리의 com.google.common.reflect 패키지에서 유틸리티 클래스를 사용할 수 있습니다. 예 :

ClassLoader cl = getClass().getClassLoader(); 
    Set<ClassPath.ClassInfo> classesInPackage = ClassPath.from(cl).getTopLevelClassesRecursive("com.mycompany.mypackage"); 

이 간결하지만 다른 답변과 같은주의 사항이 여전히 일반적으로 단지 '표준'클래스 로더 예에 의해로드 된 클래스를 찾을 것, 즉, 적용 설명합니다 : 특정 패키지의 모든 클래스를 얻을 수 있습니다 URLClassLoader.

0

스프링의 PathMatchingResourcePatternResolver을 사용하는 것이 좋습니다.

이는 IDE 또는 파일 시스템에서 패키지를 실행 모두 트릭을 할 것입니다

: 자세한 내용은

여기 내 메모를 확인 : "클래스 경로 뿌리의 의미는 무엇

How to get resources from a package

관련 문제