从@SpringBootApplication开始:
-
元注解 @Target(ElementType.TYPE) 设置当前注解可以标记在哪里 @Retention(RetentionPolicy.RUNTIME) 当注解标注的类编译以什么方式保留,runtime为可被jvm虚拟机编拟 @documented java doc可以生成注解信息 @Inherited 是否会被继承
-
@SpringBootConfiguration 元注解 @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @documented @Configuration 标注为配置类-
@EnableAutoConfiguration 开启自动配置功能 元注解 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @documented @Inherited @AutoConfigurationPackage @import(AutoConfigurationPackages.Registrar.class) register我们断点进去就会发现返回的就是类路径 所以这个注解的作用就是将当前配置类所在包保存在basePackages的Bean中。供Spring内部使用 @import(AutoConfigurationimportSelector.class) AutoConfigurationimportSelector实现的是DeferredimportSelector,而非importSelector,importSelector是通过selectimport方法通过传入类的完整限定名的数组来交由spring底层创建bean。 DeferredimportSelector第一步是看是否实现getimportGroup()方法。 如果没有实现,就是交由selectimport方法进行处理。 如果实现了,要返回一个实现了DeferredimportSelector.Group接口的类,然后调用实现了Group.process()方法,通过改方法中的getAutoConfigurationEntry获得所有的自动配置类。 在getAutoConfigurationEntry方法中有个关键的方法getCandidateConfigurations,这个方法获得了所有自动配置类(均已autoConfiguration结尾)。 进入getCandidateConfigurations方法里看看spring boot是怎么调用的。 SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass()看到这个关键方法。 getSpringFactoriesLoaderFactoryClass() factoryType.getName()里面返回了org.springframework.boot.autoconfigure.EnableAutoConfiguration 再查看loadFactoryNames方法, 会发现他去meta-INF读取spring.factories,其实就是从spring-boot,spring-beans,spring-boot-autoconfigure三个jar包中读取, 但是这些不是全都是自动配置类,再根据factoryType.getName()返回的类名当做key通过getOrDefault来做筛选,拿到其中的127个,就拿到了所有的自动配置类。 getAutoConfigurationEntry的getConfigurationClassFilter().filter(configurations)方法会根据我们在maven中添加的starter过滤出我们需要的自动配置类 后续的Group.selectimports()的方法主要是根据@order,@AutoConfigureBefor等注解进行排序。
-
-
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) 扫描包,但是并没有指定basepackage,如果没有指定spring底层会自动扫描当前配置类所有在的包 TypeExcludeFilter继承TypeFilter,实现了match方法,如果为true,则不扫描。TypeExcludeFilter是springBoot对外提供的拓展类,可以按照我们的方式进行排除,就想当于我们在xml配置中component-scan里的exclude-filter。 AutoConfigurationExcludeFilter 排除所有配置类并且是自动配置类中里面的其中一个
以HttpEncodingAutoConfiguration为例
-
@Configuration(proxyBeanMethods = false) 标识为配置类,这里标识为不代理,意味着在bean中如果引用外部bean都会new一个新的出来。
- @EnableConfigurationProperties(ServerProperties.class) 启用在配置类中可以配置的属性
可以看到批量导入属性类的注解,这就是我们可以server port进行设置端口号的原因。
-
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) @ConditionalOnClass(CharacterEncodingFilter.class) @ConditionalOnProperty(prefix = "server.servlet.encoding", value = "enabled", matchIfMissing = true) condition派生注解,作用:必须是@Conditional指定的条件成立,才给容器中添加组件,配置配里面的所有内容才生效;
| @Conditional扩展注解作用 | (判断是否满足当前指定条件) |
| @ConditionalOnJava | 系统的java版本是否符合要求 |
| @ConditionalOnBean | 容器中存在指定Bean; |
| @ConditionalOnMissingBean | 容器中不存在指定Bean; |
| @ConditionalOnexpression | 满足SpEL表达式指定 |
| @ConditionalOnClass | 系统中有指定的类 |
| @ConditionalOnMissingClass | 系统中没有指定的类 |
| @ConditionalOnSingleCandidate | 容器中只有一个指定的Bean,或者这个Bean是首选Bean |
| @ConditionalOnProperty | 系统中指定的属性是否有指定的值 |
| @ConditionalOnResource | 类路径下是否存在指定资源文件 |
| @ConditionalOnWebApplication | 当前是web环境 |
| @ConditionalOnNotWebApplication | 当前不是web环境 |
| @ConditionalOnJndi | JNDI存在指定项 |
其实在自动配置类读取流程中getConfigurationClassFilter().filter(configurations)的方法就是过滤@condition注解,看是否能找到对应的类,同时在配置文件中配置debug=true会在spring boot中显示出来使用的自动配置类
再来看方法,
这个就相当于server.servlet.encoding.charset=UTF-8,其实就是SSM中web-xml中我们配置编码的filter



