[Spring]Component Scanning

유진·2025년 2월 27일

Spring

목록 보기
6/11

Component Scanning이란?

Component Scanning이란 스프링에서 @Component가 붙은 클래스를 자동으로 검색(스캔)하여 Bean으로 등록하는 기능이다.
이는 XML 설정 없이 스프링이 직접 클래스를 찾아서 관리할 수 있도록 해준다.
guava를 사용하기 때문에 maven repository에 들어가서 의존성을 복사해 pom.xml에 추가해줘야한다. (사전 작업 필요)

Component Scanning 적용 방법

1. @Component를 사용하여 Bean 등록

@Component
public class SportsCar {
    public void drive() {
        System.out.println("스포츠카 주행 중...");
    }
}

@Component를 붙이면 스프링이 자동으로 객체를 관리한다.

2. @ComponentScan을 사용해 스캔 패키지 지정

자바 설정 기반

@Configuration
@ComponentScan(basePackages="")
public class AppConfig{}

""안에 있는 패키지에서 @Component가 붙은 클래스를 찾아서 자동으로 Bean 등록을 해준다.

xml 설정 기반

applicationContext.xml파일에 아래 코드를 넣어준다.

<context:component-scan base-package="com.example" />

"com.example" 패키지에 자동으로 Bean을 등록해준다는 의미이다.

@ComponentScan 동작원리 (직접구현)

@Component class Car{}
@Component class SportsCar extends Car{}
@Component class Truck extends Car{}
@Component class Engine{}
class AppContext{
    Map map;

    AppContext(){
        map = new HashMap();
        doComponentScan();
    }

    private void doComponentScan() {
        try {
            //1. 패키지 내의 클래스 목록을 가져옴
            ClassLoader classLoader = AppContext.class.getClassLoader();
            ClassPath classPath = ClassPath.from(classLoader);
            Set<ClassPath.ClassInfo> set = classPath.getTopLevelClasses("com.fastcampus.ch3.diCopy3");
            //2. 반복문으로 클래스를 하나씩 읽어와서 @Component가 붙어있는지 확인
            for(ClassPath.ClassInfo classInfo : set) {
                Class clazz = classInfo.load();
                Component component = (Component) clazz.getAnnotation(Component.class);
                //3. 붙어있으면 객체를 생성해서 맵에 저장
                if(component != null) {
                    String id = StringUtils.uncapitalize(classInfo.getSimpleName());
                    map.put(id,clazz.newInstance());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    Object getBean(String key){
    return map.get(key);
    }
}

public class Main3 {
    public static void main(String[] args) throws Exception {
        AppContext ac = new AppContext();
        Car car = (Car)ac.getBean("car");
        System.out.println("car: "+car);
        Engine engine = (Engine)ac.getBean("engine");
        System.out.println("engine: "+engine);
    }
}
  1. 패키지 내의 클래스 목록을 불러온다.
    ClassLoader를 선언하여 클래스를 메모리에 불러온다.
    ClassPath를 선언해서 classLoader에서 불러온 클래스의 경로를 저장한다.
    getTopLevelClasses 메서드를 활용하여 특정 패키지에 속한 최상위 클래스를 가져온다.
    반환되는 객체를 Set<ClassPath.ClassInfo> 형태의 Set에 저장한다.
    여기에는 해당 패키지에 있는 모든 클래스의 정보(이름, 경로 등)가 포함되어 있기 때문에 패키지 내에 어떤 클래스가 존재하는지 확인이 가능하다.

  2. 반복문으로 클래스를 하나씩 읽어와 @Component가 붙어있는지 확인
    Class형의 clazz에 클래스의 정보를 불러와 담는다.
    그 후 clazz.getAnnotaion 메서드를 사용하여 @Component가 붙어있는지 확인한다.
    여기서 getAnnotation 메서드는 주어진 어노테이션이 붙어있는 경우 객체를 반환하고, 붙어있지 않은 경우 null값을 반환한다.

  3. 어노테이션이 붙어있으면 객체 생성 후 맵에 저장
    위에서 getAnnotation을 한 결과가 null이 아니면 즉, @Component 어노테이션이 붙어있으면 클래스의 이름을 소문자로 변환하여 저장한다.
    (StringUtils.uncapitalize())
    그 후 map에 key와 객체(생성)를 저장한다.

0개의 댓글