소스 코드를 분석하는 자동 구성 - SpringBoot 소스 분석 (예) ----- 핵심 역량 봄 부트

이 블로그에 분석 springBoot과정, 빙산의 일반적인 개요 팁을 시작합니다. 오늘을 봐 springBoot'의 주요 기능 : 자동 조립 기능.

시작 @SpringBootApplication시작입니다. 시작 프로세스 섹션에서, 우리는 SpringBoot2 거친 시작 단계를 설명하고 소스를 설명합니다. 너무 많은 일을 할 뒤에 코드의 간단한 라인, 그러나 이것은 컨테이너, refreshContext (컨텍스트)을 새로 배치되지 않았습니다. 그래서 순서가 여기에 압도되지,이 방법은 선택하려고 관련 사항 설명 @SpringBootApplication.

클래스 로더를 시작 springBoot

우선, 스프링 springBoot 기동 클래스 용기 beanDefinitionMap 붓고로드,로드 모양 prepareContext 방법에있어서, 부하 (컨텍스트 sources.toArray (새로운 개체 [0])),
후속 결국 BeanDefinitionLoader로드 방식의 방법을 실행한다 :

개인  INT 로드 (오브젝트 소스가) { 
    Assert.notNull (출처는, "는이 null 소스를 사용해야하며" );
     // 이 클래스의 유형 인 경우, 주석 형을 사용하는 
    경우 (출처 instanceof를 <?> 클래스 {)
         반환 로드 ((클래스 <? > ) 자료); 
    }
     // 자원 유형, XML 구문 분석을 가능하게 할 경우 
    경우 소스를 ( instanceof를 자원) {
         반환 로드 ((리소스) 자료); 
    } 
    // 패키지 유형, 패키지 스캔을 사용하는 경우, 예를 들어 : @ComponentScan 
    IF ( 소스 instanceof를 패키지) {
         반환  로드 ((패키지) 자료);
    } 
    // 유형이 문자열이 직접로드되면 
    IF (출처 instanceof를 의 CharSequence) {
         반환 로드 ((CharSequence를) 자료); 
    } 
    던져  새로운 새로운 는 IllegalArgumentException ( "잘못된 입력 소스"+ source.getClass ()); 
}

후속 계속 load(Class<?> source)방법 :

시작 클래스는 @Component 어노테이션을 포함하는지 여부를 판단하는 상기 방법, 우리는 주석 카테고리를 시작할 수 없습니다. 지정된 유형도 가능하면 발견 할 것이다 후속, AnnotationUtils 재귀 구현 주석을 포함할지 여부를 결정, 노트에 노트가 포함되어 있습니다.

시작 클래스는 @SpringBootApplication 노트를 포함, 결국 @Component 메모를 발견 할 것이다, @SpringBootConfiguration 더 코멘트를 찾은 다음 @Component 메모를 찾을 수 있습니다 :

@Target (ElementType.TYPE) 
@Retention (RetentionPolicy.RUNTIME) 
@Documented @Component

 공공 @의 인터페이스 구성 { 
}

검색된 @Component주석, 물체의 표면은 상기 정보 beanDefinitaion에 포장 될 스프링 빈이, beanDefinitionMap 용기에 첨가한다. 으로는 다음과 같습니다 :

이러한 방법으로, 우리는 클래스로 포장 된 시작 AnnotatedGenericBeanDefinition의 개체를 기반으로하는 처리 이후 시작 클래스.

@EnableAutoConfiguration

@SpringBootApplication 주석 항목은 주석을 자동으로 구성 포함 :

@SpringBootConfiguration
 @EnableAutoConfiguration 
@ComponentScan (excludeFilters = { 
        @filter (타입 = FilterType.CUSTOM 클래스 = TypeExcludeFilter. 등급 ) 
        @filter (타입 = FilterType.CUSTOM 클래스 = AutoConfigurationExcludeFilter. 등급 )})
 공용 @ 인터페이스 SpringBootApplication {}

우리는 지금으로 보면 @EnableAutoConfiguration

@AutoConfigurationPackage 
@Import (EnableAutoConfigurationImportSelector. 클래스 )
 공공 @의 인터페이스 EnableAutoConfiguration {}

@AutoConfigurationPackage

  • 자동 구성 패키지 코멘트
@Import (AutoConfigurationPackages.Registrar. 클래스 )
 공공 @ 인터페이스 AutoConfigurationPackage {}

@Import (AutoConfigurationPackages.Registrar.class) : 패키지와 하위 검사의 기본 스프링 컨테이너 내부에있는 모든 구성 요소 차 패키지 구성 클래스 (@SpringBootApplication). 으로는 다음과

@Order (Ordered.HIGHEST_PRECEDENCE)
 정적  클래스 등록자가 유단 ImportBeanDefinitionRegistrar, DeterminableImports { 

    @Override 
    공개  공극 registerBeanDefinitions (AnnotationMetadata 메타, 
            BeanDefinitionRegistry에 등록) { 
         // 패키지 및 그 서브 패킷들을 스캔 기본 @SpringBootApplication 주요 구성 어디에 모든 클래스 마크 구성 요소 
        등록 (등록, 새로운 새로운 packageimport (메타 데이터) .getPackageName ()); 
    } 

    @Override 
    공개 설정 <개체> determineImports (AnnotationMetadata 메타 데이터) {
         반환 컬렉션 <개체> 싱글 (. 새로운 새로운 packageimport (메타 데이터)); 
    } 
}

@Import(EnableAutoConfigurationImportSelector.class)

EnableAutoConfigurationImportSelector : 가져 오기 선택 조립, 모든 구성 요소가 전체 클래스 이름을 리턴 방식으로 수입 할 필요가 이러한 구성 요소는 컨테이너에 추가됩니다.

1  // EnableAutoConfigurationImportSelector的父类: AutoConfigurationImportSelector 
2  @Override
 3  공개 문자열 [] selectImports (AnnotationMetadata annotationMetadata) {
 도 4      의 경우 (! 의 IsEnabled (annotationMetadata)) {
 5          리턴 NO_IMPORTS;
6      }
 7      시도 {
 8          AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
 9              .loadMetadata ( .beanClassLoader);
10 개          AnnotationAttributes 속성 = getAttributes (annotationMetadata);
(11)          목록 <문자열> 구성 = getCandidateConfigurations (annotationMetadata, 속성);
12 개          구성 = removeDuplicates (구성);
13 개          구성 = 정렬 (구성 autoConfigurationMetadata);
14          세트 <문자열> 제외 = getExclusions (annotationMetadata 속성);
15          checkExcludedClasses (구성 제외);
16          configurations.removeAll (제외);
17 개          구성 = 필터 (구성 autoConfigurationMetadata);
18          fireAutoConfigurationImportEvents (구성 제외);
19           configurations.toArray ( 새로운 문자열 [configurations.size ()]);
20      }
 21      캐치 (IOException이 예) {
 22          던질  새로운 IllegalStateException이 (예를)
23      }
 24 }

우리는 주로 처음 11 개 행을 볼 List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);것이다 선박 자동 구성 클래스 (xxxAutoConfiguration)의 다수 가득,이 시나리오는 컨테이너에 필요한 모든 구성 요소를 가져오고 이러한 구성 요소를 구성하는 것입니다. 이러한 구성 요소에 대해 또한 필터를 이러한 구성 요소를 얻을 수 있지만, 후에, 우리는 그것을 조사

보호 목록 <문자열> getCandidateConfigurations (AnnotationMetadata 메타 데이터, 
            AnnotationAttributes 속성) { 
    목록 <문자열> 구성 = SpringFactoriesLoader. loadFactoryNames ( getSpringFactoriesLoaderFactoryClass () getBeanClassLoader ());
    // ... 
    반환 구성; 
} 

보호 클래스 <?> getSpringFactoriesLoaderFactoryClass () {
     반환 EnableAutoConfiguration을. 클래스 ; 
} 

공공  정적  최종 문자열 FACTORIES_RESOURCE_LOCATION = "META-INF / spring.factories"; 

공공  정적 목록 <문자열> loadFactoryNames (<?> 클래스 factoryClass- 설정, 클래스 로더 classLoader가) { 
    문자열 FactoryClassName이 = factoryClass.getName ();
    시도 {
         // 从类路径的META-INF / spring.factories中加载所有默认的自动配置类 
        열거 <URL> URL을 = (classLoader가! = null이 ? classLoader.getResources (FACTORIES_RESOURCE_LOCATION) : 
                                 ClassLoader.getSystemResources (FACTORIES_RESOURCE_LOCATION)); 
        목록 <문자열> 결과는 = 새로운 <문자열>의 ArrayList를 ();
        동안 (urls.hasMoreElements ()) { 
            URL의 URL= urls.nextElement (); 
            속성 속성 = PropertiesLoaderUtils.loadProperties ( UrlResource를 (URL));
            // 获取EnableAutoConfiguration指定的所有值,也就是EnableAutoConfiguration.class的值 
            문자열 factoryClassNames = properties.getProperty (FactoryClassName이); 
            result.addAll (Arrays.asList (StringUtils.commaDelimitedListToStringArray (factoryClassNames))); 
        } 
        반환 결과를; 
    } 
    캐치 (IOException이 예) {
         던져  새로운 ( "[+ factoryClass.getName () +"] 위치에서 공장 [ "+ FACTORIES_RESOURCE_LOCATION +"] "로드 할 수 없습니다", IllegalArgumentException를, 예); 
    } 
}

메타 INF / spring.factories 클래스 경로 EnableAutoConfiguration 지정된 값으로부터 얻어진 시작 시간 SpringBoot,이 값이 자동으로 용기에 클래스로 구성되어, 자동 구성 등급을 적용하고, 마지막으로 상기 자동 구성을 완료. EnableAutoConfiguration 기본 스프링 부팅 자동 구성도 등이 패키지.

96 결국 자동 및 클래스는 레지스터 Spring 컨테이너에로드

우리는 또한 자동 구성 파일 콩을 작성해야 할 수도 있습니다

사용자 정의 선발

첫 번째 클래스 모듈 구성 정의 :

@Configuration 
@ConditionalOnProperty (이름 = "enabled.autoConfituration", matchIfMissing = 진정한 )
 공공  클래스 MyAutoConfiguration { 

    정적 인 { 
        에서 System.out.println ( "myAutoConfiguration 초기화 ..." ); 
    } 

    @Bean 
    공공 SimpleBean simpleBean는 () {
         반환  ) (SimpleBean을; 
    } 

}

그런 다음 스타터 모듈, 아니 코드를 정의하고, 종속성 POM하지 않고, 단지 메타-INF의 아래에 내장 된  spring.factories파일, 다음과 같은 구성을 추가 :

org.springframework.boot.autoconfigure.EnableAutoConfiguration = \ 
spring.study.startup.bean.MyAutoConfiguration

와 같이

마지막으로, 우리의 스타터 모듈 치어 수준의 프로젝트를 시작할 수 있습니다 소개합니다.

원칙

결국 AutoConfigurationImportSelector구문 분석 spring.factories파일 :

SpringBoot 구성 클래스는 180 개 이상의 우리에게 제공하지만, 우리는 모두 도입 할 수 없습니다. @Conditional 주석 조건 판단 또는 @ConditionalOnProperty 기타 관련 주석, 조립할지 여부를 결정합니다.

우리의 사용자 정의 구성 클래스가 같은 논리에서 조립, 우리는 다음과 같은 의견을 지정할 수 :

@ConditionalOnProperty (이름 = "enabled.autoConfituration", matchIfMissing = TRUE)

기본값은 스타터 정의 그래서 성공적으로 구현, 사실이다.

 

 

추천

출처www.cnblogs.com/java-chen-hao/p/11837043.html