Spring Boot実現原理


最も一般的なSprigBootアプリケーション起動クラス
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}
springbootアプリケーションは、@Spring BootAlicationの注釈を設定するだけで、自動的に起動することができます.なぜですか?
この注釈に入ると、@Spring Bootapolicationはアンノテーションを組み合わせています.その中で一番重要なannotationは@Spring BootConfigrationで、@EnbaleAutoConfigrationと@ComponentScanです. 
@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 {}
@Spring BootConfigrationは本質的には@Configrationです.スタートクラスに@Spring BootCofigrationと表示されていますが、それ自体もIOC容器の配置類です.
@ComponentScancanの注釈が完了したのは自動スキャンの機能で、Spring XML設定ファイルの中のに相当します.enclude Filters、include Filtersなどの属性を使ってスキャンするパケットを指定したり、排除したりすることができます.スキャンの条件もあります.最終的にこれらのbean定義を容器にロードする.
@Enbale AutoConfigrationは、Spring Bootの構成をこのように簡略化できるようにするためのキー注釈であり、Spring-Bootは、アプリケーションによって宣言されたjarパケット依存性に基づいてSpringフレームを自動的に配置する.たとえばspring-boot-starter-webによると ,あなたのプロジェクトがwebmvctomcatを追加する必要があるかどうかを判断すると、自動的にウェブプロジェクトに必要なデフォルトの設定を設定してくれます.
@Enbale AutoConfigration
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
//    EnableAutoConfigurationImportSelector
@Import({EnableAutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

    Class>[] exclude() default {};

    String[] excludeName() default {};
}
種類のEnbaleAutoConfigrationImportSelectorはImport Selectorインターフェースの実現類であり、ImportSelectorインターフェースのselectImportsメソッドから戻ってくるクラスはSpring容器で管理されます.
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
   
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        if (!this.isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        } else {
            try {
                //  META-INF/spring-autoconfigure-metadata.properties  
                AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
                //          
                AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
                // classpath    META-INF/spring.factories     org.springframework.boot.autoconfigure.EnableAutoConfiguration  ,        List   
                List configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
                //       List      、  
                configurations = this.removeDuplicates(configurations);
                configurations = this.sort(configurations, autoConfigurationMetadata);
                //   2                
                Set exclusions = this.getExclusions(annotationMetadata, attributes);
                this.checkExcludedClasses(configurations, exclusions);
                configurations.removeAll(exclusions);
                //         List    ,          。         org.springframework.boot.autoconfigure.condition.OnClassCondition        ConditionOutcome[]  。
                configurations = this.filter(configurations, autoConfigurationMetadata);
                this.fireAutoConfigurationImportEvents(configurations, exclusions);
                return (String[])configurations.toArray(new String[configurations.size()]);
            } catch (IOException var6) {
                throw new IllegalStateException(var6);
            }
        }
    }
}
この注釈@EnbaleAutoConfigration式はどうやって効果がありますか?
メイン起動タイプのmain関数では、SpringAppleication.run(DemoApple.class,args)を呼び出して、2ステップに分けて実行します.第1ステップはSprigAplicationオブジェクトを作成し、第2ステップはrun方法を実行します.
第一歩、SpringAppleオブジェクトの作成
このステップの主な機能はSprigAplicationオブジェクトを初期化し、クラスパスの下からMETA-INF/spring.factores配置のすべてのApplizerとApplizerを見つけて保存して、最後にmainメソッドの主な構成クラスを見つけます.
private void initialize(Object[] sources) {
    //      
    if (sources != null && sources.length > 0) {
        this.sources.addAll(Arrays.asList(sources));
    } 
    //        web  
    this.webEnvironment = deduceWebEnvironment();
    //       META‐INF/spring.factories     ApplicationContextInitializer;             
 
    setInitializers((Collection) getSpringFactoriesInstances(
    ApplicationContextInitializer.class));
    //       ETA‐INF/spring.factories     ApplicationListener
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    //          main       
    this.mainApplicationClass = deduceMainApplicationClass();
}
第二ステップ、運転run方法
run方法の重要なポイントは、IOC容器context=createApple plication Contect();最後に起動したIOC容器に戻ります.途中でrefreshContent()を呼び出し、最後にspring容器のrefreshに呼び出した場合、invokeBeanFactoryPostProcessors(beanFactory)方法でConfigrationClass PostProcessorに呼び出します.ConfigrationClass PostProcessorは私達のメインクラスを解析して@Importの中のクラスを取り出して、そのselectImports()の方法を呼び出します.その後spring容器はselectInportメソッドから返される配置類を処理します.
public ConfigurableApplicationContext run(String... args) {
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    ConfigurableApplicationContext context = null;
    FailureAnalyzers analyzers = null;
    configureHeadlessProperty();
    //  SpringApplicationRunListeners;     META‐INF/spring.factories
    SpringApplicationRunListeners listeners = getRunListeners(args);
    //       SpringApplicationRunListener.starting()  
    listeners.starting();
    try {
        //       
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(
    args);
        //    
        ConfigurableEnvironment environment = prepareEnvironment(listeners,
    applicationArguments);
        //         SpringApplicationRunListener.environmentPrepared();     
       
        Banner printedBanner = printBanner(environment);
        //  ApplicationContext;    web ioc     ioc
        context = createApplicationContext();
        analyzers = new FailureAnalyzers(context);
        //       ; environment   ioc ;  applyInitializers();
        //applyInitializers():          ApplicationContextInitializer initialize  
        //     SpringApplicationRunListener contextPrepared();
        //
        prepareContext(context, environment, listeners, applicationArguments,
    printedBanner);
        //prepareContext           SpringApplicationRunListener contextLoaded();
        //s    ;ioc     (   web          Tomcat);Spring   
        //  ,  ,         ;(   ,  ,    )
        refreshContext(context);
        // ioc        ApplicationRunner CommandLineRunner    
        //ApplicationRunner   ,CommandLineRunner   
        afterRefresh(context, applicationArguments);
        //   SpringApplicationRunListener  finished  
        listeners.finished(context, null);
        stopWatch.stop();
        if (this.logStartupInfo) {
        new StartupInfoLogger(this.mainApplicationClass)
        .logStarted(getApplicationLog(), stopWatch);
        }
        //  SpringBoot             ioc  ;
        return context;
    } catch (Throwable ex) {
        handleRunFailure(context, listeners, analyzers, ex);
        throw new IllegalStateException(ex);
    }
}