内容出自《Spring源码深度解析》
我们已经知道了Spring Boot如何启动Spring,但是目前为止我们并没有揭开Spring Boot的面纱,究竟Starter是如何生效的呢?这些逻辑现在看来只能体现在注解SpringBootApplication本身了。
查看启动类的@SpringBootApplication注解:
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package org.springframework.boot.autoconfigure; import java.lang.annotation.*; import org.springframework.*; @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 { @AliasFor( annotation = EnableAutoConfiguration.class ) Class<?>[] exclude() default {}; @AliasFor( annotation = EnableAutoConfiguration.class ) String[] excludeName() default {}; @AliasFor( annotation = ComponentScan.class, attribute = "basePackages" ) String[] scanBasePackages() default {}; @AliasFor( annotation = ComponentScan.class, attribute = "basePackageClasses" ) Class<?>[] scanBasePackageClasses() default {}; }这里面我们更关注SpringBootApplication上的注解内容,因为注解具有传递性,EnableAutoConfiguration是个非常特别的注解,它是Spring Boot的全局开关,如果把这个注解去掉,则一切Starter都会失效,这就是约定大于配置的潜规则,那么,Spring Boot的核心很可能就藏在这个注解里面:
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package org.springframework.boot.autoconfigure; import java.lang.annotation.*; import org.springframework.context.annotation.Import; @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 {}; }AutoConfigurationImportSelector作为Starter自动化导入的关键选项终于浮现出来,那么Spring是怎么识别并让这个注解起作用的呢?我们看到这个类中只有一个方法,那么只要看一看到底是哪个方法调用了它,就可以顺藤摸瓜找到最终的调用点。