왜 나 는 spring. factories 파일 을 써 야 합 니까?안 써 도 돼 요?

5542 단어 자바spring
spring - boot 관련 소스 코드 를 읽 을 때 spring. factories 파일 을 자주 볼 수 있 습 니 다. 자동 설정 (AutoConfiguration) 과 관련 된 클래스 이름 이 적 혀 있어 서 의문 이 생 겼 습 니 다. "자동 으로 설 정 된 클래스 에 @ Configuration 의 주 해 를 달 았 는데 왜 spring. factories 파일 을 써 야 합 니까?"
이 화 제 는 @ SpringBootApplication 주해 부터 시작 해 야 합 니 다.
@ SpringBootApplication 소스 코드 를 보면 계승 할 다음 주 해 를 볼 수 있 습 니 다.
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
        @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
    ……
}

그 중에서 중요 한 것 은 @ EnableAutoConfiguration 과 @ ComponentScan 두 개의 주석 입 니 다. @Componentscan 주 해 는 @ SpringBootApplication 이 있 는 Application 류 (즉, spring - boot 프로젝트 의 입구 류) 가 있 는 가방 (basepackage) 에 있 는 모든 @ component 주해 (또는 @ component 의 주해) 표 시 된 bean 을 스 캔 하여 spring 용기 에 등록 하 는 역할 을 합 니 다.
spring - boot 프로젝트 에 pom 파일 에 추 가 된 의존 하 는 bean (spring - boot 프로젝트 밖의 bean) 이 spring - boot 프로젝트 의 spring 용기 에 어떻게 등록 되 었 는 지 의문 이 있 을 수 있 습 니 다.
@ EnableAutoConfiguration 의 역할 에 대해 논의 해 야 합 니 다.@ EnableAutoConfiguration 원본 보기,
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
    Class>[] exclude() default {};
    String[] excludeName() default {};
}

중요 한 코드 는 @ Import (AutoConfiguration ImportSelector. class) 이 고, AutoConfiguration ImportSelector. class 는 무엇 을 했 습 니까?그 소스 코드 를 통 해 알 수 있 듯 이 관건 적 인 부분 은...
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
    if (!isEnabled(annotationMetadata)) {
        return NO_IMPORTS;
    }
    AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
            .loadMetadata(this.beanClassLoader);
    AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,
            annotationMetadata);
    return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}

그 중에서 getAutoConfigurationEntry 방법 은 spring - boot 프로젝트 에서 자동 으로 설정 해 야 할 항목 (bean) 을 가 져 왔 습 니 다. 원본 코드 를 보면
protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
        AnnotationMetadata annotationMetadata) {
    if (!isEnabled(annotationMetadata)) {
        return EMPTY_ENTRY;
    }
    AnnotationAttributes attributes = getAttributes(annotationMetadata);
    List configurations = getCandidateConfigurations(annotationMetadata, attributes);
    configurations = removeDuplicates(configurations);
    Set exclusions = getExclusions(annotationMetadata, attributes);
    checkExcludedClasses(configurations, exclusions);
    configurations.removeAll(exclusions);
    configurations = filter(configurations, autoConfigurationMetadata);
    fireAutoConfigurationImportEvents(configurations, exclusions);
    return new AutoConfigurationEntry(configurations, exclusions);
}

그 중에서 가장 중요 한 부분 은 getCandidate Configurations 방법 입 니 다. 프로젝트 에 참여 할 수 있 는 모든 후보 설정 bean 을 가 져 왔 습 니 다. 이에 대응 하 는 getExclusions 는 불 러 올 필요 가 없 는 모든 설정 bean 을 가 져 왔 습 니 다.getCandidate Configurations 방법의 원본 코드 를 더 살 펴 보고,
protected List getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    List configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
            getBeanClassLoader());
    Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
            + "are using a custom packaging, make sure that file is correct.");
    return configurations;
}

이 방법의 구체 적 인 실현 은 spring - boot 프로젝트 의 classpath 에서 META - INF/spring. factories 의 내용 을 읽 는 것 입 니 다. 이 파일 은 항상 K/V 형식 으로 데 이 터 를 저장 합 니 다. 예 를 들 어:
# Auto Configuration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.HelloAutoConfiguration,\
……

getCandidate Configurations 방법 은 자동 으로 설정 해 야 할 클래스 를 가 져 옵 니 다. 위 에서 말 한 설정 클래스 를 제외 하고 다른 클래스 는 spring - boot 프로젝트 의 spring 용기 에 등 록 됩 니 다.
이 를 보면 @ EnableAutoConfiguration 주해 의 작업 원 리 를 알 고 있 을 것 입 니 다. "spring. factories 파일 을 왜 썼 습 니까?"
앞에서 제시 한 의문 과 결합 하여 "spring - boot 프로젝트 에 pom 파일 에 추 가 된 의존 중의 bean 은 어떻게 spring - boot 프로젝트 의 spring 용기 에 등록 되 었 습 니까?"spring. factories 파일 은 spring - boot 프로젝트 패키지 이외 의 bean (즉, pom 파일 에 의존 하 는 bean 추가) 을 spring - boot 프로젝트 에 등록 하 는 spring 용기 라 는 결론 을 얻 기 어렵 지 않 습 니 다.@ Componentscan 주 해 는 spring - boot 프로젝트 패키지 안의 bean 만 스 캔 하고 spring 용기 에 등록 할 수 있 기 때문에 프로젝트 패키지 밖의 bean 을 등록 하려 면 @ EnableAutoConfiguration 주해 가 필요 합 니 다.spring. factories 파일 은 프로젝트 패키지 외 에 등록 해 야 할 bean 클래스 를 기록 하 는 데 사 용 됩 니 다. 
대형 프로젝트 를 구축 할 때 외부 의존 패키지 (spring - boot - starter - xxx 와 유사) 를 직접 쓸 수도 있 습 니 다.주 항목 에 이 외부 의존 패 키 지 를 추가 한 후, 이 외부 의존 패키지 안의 bean 은 주 항목 의 spring 용기 에 자동 으로 가입 해 야 할 때 (@ Bean 을 수 동 으로 추가 하 는 것 이 아니 라) 본 고의 방법 을 사용 해 야 합 니 다.이런 방법 을 쓰 고 싶 지 않 으 면 다른 방법 이 있 습 니까?어떤 것 은 @ Bean 라벨 을 직접 수 동 으로 추가 하면 됩 니 다.

좋은 웹페이지 즐겨찾기