@Import

2023. 5. 4. 13:35Spring Boot/Spring Boot Auto Configuration

🌿 Spring @Import 어노테이션 정리

@ImportSpring Framework에서 구성(Configuration) 메타데이터를 추가하는 방법 중 하나입니다.
이를 통해 다른 구성 클래스를 로드 하거나, 동적으로 빈을 등록 할 수 있습니다.
사용 방식에 따라 정적(Static) 방법동적(Dynamic) 방법으로 나뉩니다.

1️⃣ 정적(Static) 방법: 직접 클래스 지정

가장 기본적인 @Import 사용 방식으로, 한 개 또는 여러 개의 구성 클래스를 직접 명시 합니다.

@Configuration
@Import({ConfigA.class, ConfigB.class})
public class MainConfig {
    // ...
}

📌 작동 방식
ConfigAConfigB에 정의된 빈들이 Spring 컨텍스트에 등록
✅ 컴파일 시점에 결정되므로 정적인 방법

2️⃣ 동적(Dynamic) 방법: ImportSelector & ImportBeanDefinitionRegistrar 사용

동적 방법에서는 구성 클래스를 프로그래밍 방식으로 결정하여 등록 할 수 있습니다.

(1) ImportSelector 사용

ImportSelector의 selectImports() 메서드를 구현하여 등록할 클래스 목록을 동적으로 반환 합니다.

public class MyImportSelector implements ImportSelector {

    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[] {
            "com.example.config.ServiceConfigA",
            "com.example.config.ServiceConfigB"
        };
    }
}

📌 작동 방식
selectImports() 메서드에서 등록할 설정 클래스의 FQCN(완전한 클래스명)을 반환
@Configuration이나 @Component가 적용된 클래스들을 스프링 컨텍스트에 추가
✅ 특정 조건에 따라 다른 클래스를 등록 가능 → 유연한 설정 가능

🛠 사용 예제

@SpringBootApplication
@Import(MyImportSelector.class)  // ImportSelector 등록
public class ImportSelectorApplication implements CommandLineRunner {

    private final ApplicationContext context;

    public ImportSelectorApplication(ApplicationContext context) {
        this.context = context;
    }

    public static void main(String[] args) {
        SpringApplication.run(ImportSelectorApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        System.out.println("Bean serviceA: " + context.getBean("serviceA"));
        System.out.println("Bean serviceB: " + context.getBean("serviceB"));
    }
}

🛠 실행 결과

Bean serviceA: Service A Bean
Bean serviceB: Service B Bean

(2) ImportBeanDefinitionRegistrar 사용

ImportBeanDefinitionRegistrarSpring 컨텍스트에 빈을 프로그래밍 방식으로 등록 할 수 있습니다.
이 방식은 더 정밀한 제어가 필요할 때 사용됩니다.

📌 주요 메서드

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        if (!registry.containsBeanDefinition("customService")) {
            RootBeanDefinition beanDefinition = new RootBeanDefinition(CustomService.class);
            registry.registerBeanDefinition("customService", beanDefinition);
            System.out.println("customService 빈 등록 완료");
        }
    }
}

📌 작동 방식
registerBeanDefinitions()에서 Spring 컨텍스트에 동적으로 빈을 등록
✅ 특정 조건에 따라 빈을 등록 가능
✅ 기존 빈이 등록되어 있는지 확인 후, 중복 방지 가능

🛠 사용 예제

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(MyImportBeanDefinitionRegistrar.class)
public @interface EnableMyFeature {
}
@SpringBootApplication
@EnableMyFeature  // 커스텀 애노테이션 사용
public class ImportBeanDefinitionRegistrarApplication {

    public static void main(String[] args) {
        ApplicationContext context = SpringApplication.run(ImportBeanDefinitionRegistrarApplication.class, args);

        CustomService customService = context.getBean(CustomService.class);
        customService.performAction();
    }
}

🛠 실행 결과

customService 빈 등록 완료
Performing custom service action

3️⃣ ImportSelector vs. ImportBeanDefinitionRegistrar 비교

기능 ImportSelector ImportBeanDefinitionRegistrar
클래스 등록 방식 구성 클래스(@Configuration) 자체를 등록 구성 클래스 외에도 개별 빈 정의 등록 가능
리턴 타입 클래스명(String 배열) BeanDefinitionRegistry를 이용해 직접 등록
유연성 상대적으로 제한적 더 정밀한 제어 가능
주 사용 목적 특정 환경에 따라 설정 클래스를 동적으로 로드 복잡한 빈 설정, 런타임에 등록

📌 ImportSelector설정 클래스 를 동적으로 가져오는 데 사용
📌 ImportBeanDefinitionRegistrar구체적인 빈 정의를 직접 등록 가능

4️⃣ 응용 사례

정적 구성(@Import)

  • @Configuration 클래스를 명시적으로 불러와 컴파일 시점에 결정된 설정 클래스 등록

ImportSelector

  • 특정 조건에 따라 어떤 설정 클래스를 로드할지 결정 (예: 환경별 설정)

ImportBeanDefinitionRegistrar

  • 특정 상황에서 별도의 빈을 수동으로 등록 (예: 외부 라이브러리 지원)

🎯 결론

🔹 @Import 를 사용하면 정적/동적 방식으로 구성 클래스를 스프링 컨텍스트에 등록 가능
🔹 ImportSelector설정 클래스 자체를 동적으로 등록
🔹 ImportBeanDefinitionRegistrar개별 빈을 정밀하게 등록 가능
🔹 애플리케이션 요구사항에 따라 적절한 방법을 선택하여 활용 가능 🚀

'Spring Boot > Spring Boot Auto Configuration' 카테고리의 다른 글

@EnableAutoConfiguration  (0) 2024.10.16
@SpringBootConfiguration  (0) 2024.10.16
SpringApplication.run  (0) 2024.10.16
@SpringBootApplication  (0) 2024.10.16
Classpath  (0) 2024.10.16