Spring - 자동 객체 등록하기(Component Scanning)

김도형·2023년 1월 29일
0

먼저 guava, springframework 라이브러리를 사용해야한다.

요구사항

  • 패키지 내의 모든 클래스를 읽어서 set에 저장
  • 패지키 내에 @Component 붙은 클래스 찾기
  • 객체 생성해서 map에 저장(단, key 이름은 Car -> car 소문자로 변경해서 저장)

자동 객체 등록 시 장점

  • 외부 파일로 수동 객체를 등록 따로 관리 포인트를 가지는 것보다 객체를 생성할 클래스에@Component 만 붙여 주면 돼서, 관리점이 줄어드는 장점을 가진다.

코드

@Component 붙여진 대상들은 com.fastcampus.ch3.diCopy3 위치한다.

package com.fastcampus.ch3.diCopy3;

import com.google.common.reflect.ClassPath;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

@Component class Car {}
@Component class SportsCar extends Car {}
@Component class Truck extends Car {}
@Component class Engine extends Car {}

class AppConext {
    Map map; // 객체 저장소

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

    private void doComponentScan() {
        try {
            // 1. 패키지내의 클래스 목록을 가져온다.
            ClassLoader classLoader = AppConext.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. @Component가 붙어있으면 객체를 생성해서 map에 저장
                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 {
		AppConext ac = new AppConext();
        Car car = (Car) ac.getBean("car");
        Engine engine = (Engine) ac.getBean("engine");
        Car sportsCar = (Car) ac.getBean("sportsCar");
        Car truck = (Car) ac.getBean("truck");
        System.out.println("car = " + car);
        System.out.println("engine = " + engine);
        System.out.println("sportsCar = " + sportsCar);
        System.out.println("truck = " + truck);
    }

}

결과

아래 결과를 보면 알겠지만 현재 Map의 key-value 는 아래 표와 같이 구성되어 있다.

Keyvalue
car@612fc6eb
engine@1060b431
sportsCar@612679d6
truck@11758f2a
car = diCopy2.Car@612fc6eb
engine = diCopy2.Engine@1060b431
sportsCar = diCopy2.SportsCar@612679d6
truck = diCopy2.Truck@11758f2a

Component 애너테이션을 삭제할 경우

Car 객체이 있는 @Component 삭제하면 어떻게 결과가 나올까

class Car {}

결과 @Component 스캔하지 못해 map 에는 Car 객체가 등록되지 않음(null)

car = null

출처 : 남궁성 저자의 스프링의 정석(패스트 캠퍼스)(https://fastcampus.co.kr/dev_academy_nks)

profile
3년간 웹/앱, 자동제어 QA 🔜 개발자로 전향하여 현재 교육 회사에서 백엔드 개발자로 근무 중입니다.(LinkedIn : https://www.linkedin.com/in/dohyoung-kim-5ab09214b)

0개의 댓글