이제 스캔(scan)한 모든 클래스 파일(.class)들을 "Class.forName"으로 읽어 클래스 배열(List<Class<?>>)로 리턴하여 처리하겠습니다.
1. "TestClassScanner.java"에서 "void"로 리턴되는 "scan"메소드를 클래스 배열("List<Class>")로 리턴하게 수정하고 클래스 배열 변수를 생성하고 리턴합니다.
public static List<Class<?>> scan(String basePackageName) {
List<Class<?>> classes = new ArrayList<Class<?>>();
return classes;
}
"findClasses"메소드에 파라메타로 베이스 페키지 경로를 추가합니다.
classes.addAll(findClasses(file, basePackageName));
"scan"메소드 전체 소스입니다.
/**
* 베이스 패키지 경로로 리소스를 스캔합니다.
* @param basePackageName 베이스 패키지 경로
* @return 클래스 배열
*/
public static List<Class<?>> scan(String basePackageName) {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
String path = basePackageName.replace('.', '/');
List<Class<?>> classes = new ArrayList<Class<?>>();
try {
List<File> files = new ArrayList<File>();
Enumeration<URL> resources = classLoader.getResources(path);
while (resources.hasMoreElements()) {
URL resource = resources.nextElement();
files.add(new File(resource.getFile()));
}
for (File file : files) {
if (file.isDirectory()) {
//System.out.println("[Directory] " + file.getAbsolutePath());
classes.addAll(findClasses(file, basePackageName));
}
}
} catch (IOException e) {
e.printStackTrace();
}
return classes;
}
2. "TestClassScanner.java"에서 "void"로 리턴되는 "findClasses"메소드를 클래스 배열("List<Class>")로 리턴하게 수정하고 파라메타로 베이스 페키지 경로를 추가하고 클래스 배열 변수를 생성하고 리턴합니다.
private static List<Class<?>> findClasses(File directory, String packageName) {
List<Class<?>> classes = new ArrayList<Class<?>>();
if (!directory.exists()) {
return classes;
}
return classes;
}
디렉토리이면 패키지(package)임으로 패키지(package) 파라메타에 디렉토리(패키지)명을 추가하여 재귀호출(recursive call)로 다시 "findClasses"를 호출하게 합니다.
classes.addAll(findClasses(file, packageName + "." + file.getName()));
"Class.forName"를 이용하여 클래스 파일(.class)을 로드하여 클래스 배열에 추가합니다.
String className = packageName + '.' + file.getName().substring(0, file.getName().length() - 6);
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
try {
classes.add(Class.forName(className, false, classLoader));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
"findClasses"메소드 전체 소스입니다.
/**
* 모든 리소스 디렉토리를 검색하여 클래스 파일(.class)을 찾습니다.
* @param directory 리소스 디렉토리
* @param packageName 패키지 경로
* @return 클래스 배열
*/
private static List<Class<?>> findClasses(File directory, String packageName) {
List<Class<?>> classes = new ArrayList<Class<?>>();
if (!directory.exists()) {
return classes;
}
File[] files = directory.listFiles();
for (File file : files) {
if (file.isDirectory()) {
//System.out.println("[Directory] " + file.getAbsolutePath());
classes.addAll(findClasses(file, packageName + "." + file.getName()));
} else if (file.getName().endsWith(".class")) {
//System.out.println("[File] " + file.getAbsolutePath());
String className = packageName + '.' + file.getName().substring(0, file.getName().length() - 6);
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
try {
classes.add(Class.forName(className, false, classLoader));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
return classes;
}
3. "TestServletContextListener.java"에서 "contextInitialized"를 수정합니다.
List<Class<?>> classes = TestClassScanner.scan(basePackage);
for (Class<?> findClass : classes) {
System.out.println("[Class] " + findClass.getName());
}
4. "Servers"탭에서 "tomcat8"를 선택하고 "start"버튼(start the server)을 클릭합니다.
"Console"탭을 클릭하면 지금까지 "com.home.project.test2"를 베이스로 만들어진 모든 클래스들이 로드되어 출력된 것을 확인할 수 있습니다.