본문 바로가기
Spring/인프런 토비의 Spring Boot

섹션 6-6 [자동 구성 기반 애플리케이션] 자동 구성 정보 파일 분리

by include_hoany 2024. 6. 14.

자동 구성 정보 파일 분리

package com.tobyspring.config;  
  
import org.springframework.boot.context.annotation.ImportCandidates;  
import org.springframework.context.annotation.DeferredImportSelector;  
import org.springframework.core.type.AnnotationMetadata;  
  
import java.util.stream.StreamSupport;  
  
/*  
    DeferredImportSelector을 구현하여 config class의  
    이름을 selectImports 메소드를 통해 Sring배열로 리턴합니다.  
 */  
/*  
    classLoader를 Spring Container로 부터 주입받아서 사용할 수 있습니다.  
    지금은 생성자로 주입받았지만 BeanClassLoaderAware 인터페이스를 구현하여 주입받을  
    수도 있습니다.  
 */
 public class MyAutoConfigImportSelector implements DeferredImportSelector {  
  
    private final ClassLoader classLoader;  
  
    public MyAutoConfigImportSelector(ClassLoader classLoader) {  
        this.classLoader = classLoader;  
    }  
  
    /*  
        구성정보로 사용될 후보 클래스들을 불러오는 작업을 합니다.  
     */    @Override  
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {  
        /*  
            ImportCandidates.load를 통해 파일로부터 구성정보를 읽어낼때  
            META-INF/spring/%s.imports 경로의 파일을 확인하여 가져옵니다.  
         */        Iterable<String> candidates = ImportCandidates.load(MyAutoConfiguration.class, classLoader);  
        return StreamSupport.stream(candidates.spliterator(), false).toArray(String[]::new);  
    }  
  
}

기존에 클래스 이름을 직접 하드코딩하는 방법에서 파일로부터 구성정보를 입력받기 위해서는 ImportCandidates.load() 메소드를 통해 입력받을 수 있습니다. load메소드는 두가지를 매개변수로 받는데 @Import에 등록할 class의 클래스 타입과 Spring Contianer에서 관리되는 ClassLoader를 매개변수로 입력받게 됩니다.

 

public static ImportCandidates load(Class<?> annotation, ClassLoader classLoader) {  
    Assert.notNull(annotation, "'annotation' must not be null");  
    ClassLoader classLoaderToUse = decideClassloader(classLoader);  
    String location = String.format("META-INF/spring/%s.imports", annotation.getName());  
    Enumeration<URL> urls = findUrlsInClasspath(classLoaderToUse, location);  
    List<String> importCandidates = new ArrayList();  
  
    while(urls.hasMoreElements()) {  
        URL url = (URL)urls.nextElement();  
        importCandidates.addAll(readCandidateConfigurations(url));  
    }  
  
    return new ImportCandidates(importCandidates);  
}

또한 파일로부터 구성정보를 입력받기 위해서는 파일에 해당 구성정보들이 기입되어 있어야 하는데
ImpoerCandidates.load 구현 정보를 확인해보면 META-INF/spring/%s.imports경로의 파일들을 읽어오는걸 확인할 수 있습니다. 해당 경로에 구성정보를 담은 파일을 작성해서 구성정보를 불러올 수 있게 구현할 수 있습니다.

 

resources/META-INF/spring/com.tobyspring.confug.MyAutoConfiguration.imports

com.tobyspring.config.autoconfig.TomcatWebServerConfig  
com.tobyspring.config.autoconfig.DispatcherServletConfig

위 구성정보를 통해 동적으로 구성정보를 입력받을 수 있게 됩니다.