package ex04;
import java.io.File;
import java.net.URL;
public class App {
public static void main(String[] args) {
// 1. @Component가 붙으면 new해서 컬렉션에 담기
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
URL packageUrl = classLoader.getResource("ex04");
File packageDir = new File(packageUrl.getFile());
for (File file : packageDir.listFiles()) {
if (file.getName().endsWith(".class")) {
String className = "ex04." + file.getName().replace(".class", "");
System.out.println(className);
}
}
}
} 
package ex04;
import java.io.File;
import java.net.URL;
import java.util.HashSet;
import java.util.Set;
public class App {
public static void main(String[] args) {
// 1. @Component가 붙으면 new해서 컬렉션에 담기
Set<Object> instances = new HashSet();
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
URL packageUrl = classLoader.getResource("ex04");
File packageDir = new File(packageUrl.getFile());
for (File file : packageDir.listFiles()) {
if (file.getName().endsWith(".class")) {
String className = "ex04." + file.getName().replace(".class", "");
//System.out.println(className);
try {
Class cls = Class.forName(className);
if (cls.isAnnotationPresent(Component.class)) {
Object instance = cls.getDeclaredConstructor().newInstance();
instances.add(instance);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
// for 종료
for (Object instance : instances) {
System.out.println(instance.getClass().getName());
}
}
}1️⃣ Set<Object> instances = new HashSet();
- instances는 @Component가 붙은 클래스들의 인스턴스를 저장하는 **컬렉션(Set)**입니다.
- HashSet을 사용했기 때문에 중복이 허용되지 않습니다.
2️⃣ 패키지(ex04) 내부의 .class 파일을 탐색
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
URL packageUrl = classLoader.getResource("ex04");
File packageDir = new File(packageUrl.getFile());- *ClassLoader*를 이용하여 ex04 패키지의 URL을 가져옵니다.
- 이 URL을 이용해 File 객체로 변환하여 실제 파일 시스템에서 ex04 패키지의 클래스 파일들을 탐색할 준비를 합니다.
3️⃣ .class 파일 목록을 가져와 클래스 이름으로 변환
for (File file : packageDir.listFiles()) {
if (file.getName().endsWith(".class")) {
String className = "ex04." + file.getName().replace(".class", "- 패키지(ex04) 내부의 파일들을 가져와 .class 확장자로 끝나는 파일만 골라냅니다.
- 파일명을 **클래스 이름(ex04.클래스명)**으로 변환하여 동적으로 클래스를 로드할 준비를 합니다.
4️⃣ 리플렉션을 사용하여 클래스 정보를 로드
Class cls = Class.forName(className);- Class.forName(className) → className을 이용해 **실제 클래스 객체(Class 타입)**를 가져옵니다.
- 이렇게 하면 해당 클래스에 대한 정보를 동적으로 가져올 수 있습니다.
5️⃣ @Component가 붙어 있는지 확인
if (cls.isAnnotationPresent(Component.class)) {- cls.isAnnotationPresent(Component.class) → 해당 클래스에 @Component 어노테이션이 붙어 있는지 검사합니다. → true면 자동으로 인스턴스를 생성하고 instances에 추가합니다.
6️⃣ 객체를 생성하고 컬렉션(Set)에 저장
Object instance = cls.getDeclaredConstructor().newInstance();
instances.add(instance);- cls.getDeclaredConstructor().newInstance() → 클래스의 기본 생성자를 호출하여 객체를 동적으로 생성합니다. → 생성된 객체를 instances(Set)에 저장합니다.
7️⃣ @Component가 붙은 클래스들의 인스턴스 목록 출력
for (Object instance : instances) {
System.out.println(instance.getClass().getName());
}- instances에 저장된 객체들의 클래스 이름을 출력합니다.
- 즉, @Component가 붙은 클래스들의 이름이 콘솔에 출력됩니다.
package ex04;
import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.HashSet;
import java.util.Set;
public class DispatcherServlet {
public Set<Object> componentScan(String packageName) {
// 1. @Component가 붙으면 new해서 컬렉션에 담기
Set<Object> instances = new HashSet();
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
URL packageUrl = classLoader.getResource(packageName);
File packageDir = new File(packageUrl.getFile());
for (File file : packageDir.listFiles()) {
if (file.getName().endsWith(".class")) {
String className = packageName + "." + file.getName().replace(".class", "");
//System.out.println(className);
try {
Class cls = Class.forName(className);
if (cls.isAnnotationPresent(Component.class)) {
Object instance = cls.getDeclaredConstructor().newInstance();
instances.add(instance);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
} // for 종료
return instances;
}
public void routing(Set<Object> instances, String path) {
for (Object instance : instances) {
Method[] methods = instance.getClass().getMethods();
for (Method method : methods) {
RequestMapping rm = method.getAnnotation(RequestMapping.class);
if (rm == null) continue; // 다음 for문으로 바로 넘어감
if (rm.value().equals(path)) {
try {
method.invoke(instance);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
}
}package ex04;
@Component
public class BoardController {
@RequestMapping("/write")
public void write() {
System.out.println("write call");
}
@RequestMapping("/delete")
public void delete() {
System.out.println("delete call");
}
}package ex04;
@Component
public class UserController {
@RequestMapping("/login")
public void login() {
System.out.println("login call");
}
@RequestMapping("/join")
public void join() {
System.out.println("join call");
}
@RequestMapping("/logout")
public void logout() {
System.out.println("logout call");
}
@RequestMapping("/userinfo")
public void userinfo() {
System.out.println("userinfo call");
}
}package ex04;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE) // 클래스 위 !
public @interface Component {
}
package ex04;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME) // 메서드가 오류 발생 시 알려줌
@Target(ElementType.METHOD) // METHOD 메서드 위에만 붙힐 수 있다. (Class 위에 붙히려면 type을 적어야함)
public @interface RequestMapping {
String value();
}

Share article