Java 프레임워크 만들기 - JSP

자바 프로젝트 패키지에 있는 클래스 스캔(Class.forName) 2 - Java Project Package Class Scan, 이클립스(Eclipse)

carrotweb 2021. 4. 27. 16:53
728x90
반응형

이제 스캔(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"를 베이스로 만들어진 모든 클래스들이 로드되어 출력된 것을 확인할 수 있습니다.

728x90
반응형