Spring Boot 자동 구성 및 빈 주입 메커니즘 심층 분석

Spring Boot의 자동 구성 작동 원리

Spring Boot 애플리케이션이 시작되면 @EnableAutoConfiguration 어노테이션이 핵심적인 역할을 수행한다. 이 어노테이션은 내부적으로 @Import(AutoConfigurationImportSelector.class)를 포함하고 있으며, 이를 통해 수많은 자동 구성 클래스들을 조건에 따라 선택적으로 로드하게 된다.

AutoConfigurationImportSelectorImportSelector 인터페이스를 구현하며, selectImports() 메서드를 오버라이드하여 조건 기반으로 구성 클래스를 필터링한다. 해당 메서드는 SpringFactoriesLoader를 사용해 클래스패스 내 META-INF/spring.factories 파일에서 org.springframework.boot.autoconfigure.EnableAutoConfiguration 키에 매핑된 모든 자동 구성 클래스 목록을 읽어들인다.

읽어들인 구성 클래스들은 각각 @ConditionalOnClass, @ConditionalOnMissingBean 등의 조건 어노테이션을 기반으로 평가되며, 애플리케이션의 현재 환경과 의존성에 부합하는 경우에만 최종적으로 스프링 컨텍스트에 등록된다. 이러한 과정을 통해 Spring Boot는 개발자가 명시적으로 빈을 정의하지 않아도 필요한 컴포넌트를 자동으로 설정한다.

비-Spring 관리 객체에서 빈 사용하기

스프링 컨테이너 외부에서 생성된 클래스(예: new 키워드로 직접 인스턴스화된 클래스)는 기본적으로 의존성 주입을 받을 수 없다. 그러나 다음과 같은 방법을 통해 여전히 스프링 빈을 활용할 수 있다.

1. XML 기반 빈 정의

XML 설정 파일을 사용할 경우, 비-Spring 객체도 빈으로 등록한 후 다른 스프링 빈에 주입할 수 있다.

<bean id="externalService" class="com.example.ExternalService"/>

<bean id="applicationService" class="com.example.ApplicationService">
    <property name="service" ref="externalService"/>
</bean>

대상 클래스에서는 일반적인 setter 또는 생성자 주입 방식을 사용하면 된다.

public class ApplicationService {
    private ExternalService service;

    public void setService(ExternalService service) {
        this.service = service;
    }
}

2. @Autowired를 통한 자동 주입

컴포넌트 스캔이 활성화된 환경에서는 @Autowired를 사용해 의존성을 자동으로 연결할 수 있다. 단, 이 경우에도 대상 클래스가 반드시 스프링 빈이어야 한다.

<context:component-scan base-package="com.example" />
public class ApplicationService {

    @Autowired
    private ExternalService service;
}

3. 정적 컨텍스트를 통한 수동 빈 획득

정적 필드나 정적 메서드 내에서 스프링 빈을 사용해야 하는 경우, 컨텍스트를 직접 참조하여 빈을 조회하는 유틸리티 클래스를 사용하는 것이 일반적이다. 다음은 그 예시이다.

public class BeanContext {

    private static ApplicationContext context;

    public static void initialize(ApplicationContext applicationContext) {
        context = applicationContext;
    }

    public static <T> T lookup(Class<T> beanType) {
        if (context == null) {
            throw new IllegalStateException("애플리케이션 컨텍스트가 초기화되지 않았습니다.");
        }
        return context.getBean(beanType);
    }
}

이러한 유틸리티를 기반으로 정적 멤버 초기화가 가능하다.

public class StaticComponent {

    private static DataService dataService;

    static {
        // 애플리케이션 컨텍스트가 준비된 후 호출되어야 함
        dataService = BeanContext.lookup(DataService.class);
    }

    public static void processData() {
        dataService.execute();
    }
}

주의할 점은 정적 블록이 클래스 로딩 시점에 실행되므로, 스프링 컨텍스트가 이미 구축된 상태에서 클래스가 로드되어야 한다는 것이다. 그렇지 않으면 NullPointerException 또는 컨텍스트 미생성 예외가 발생할 수 있다.

태그: Spring Boot 자동 구성 @EnableAutoConfiguration ApplicationContext @Autowired

6월 23일 17:59에 게시됨