[TOC]
- 标记该类为主配置类
- 运行该类 main() 启动整个 SpringBoot 应用
- 描述注解的使用范围
CONSTRUCTOR
:描述构造器FIELD
:描述字段LOCAL_VARIABLE
:描述局部变量METHOD
:描述方法PACKAGE
:描述包PARAMETER
:描述参数TYPE
:描述类、接口、枚举
- 标记注解会被保留到哪个阶段
RUNTIME
:被 JVM 保留,在运行时能被 JVM 或 其他反射机制读取和使用CLASS
:编译时保留,class文件中存在,JVM中忽略SOURCE
:源码保留,编译忽略
- 生成 Java Doc
- 标记会被自动继承(子类继承父类所有属性)
- 标记为 SpringBoot 配置类
- 标记开启自动装配
- 扫描包(扫描指定路径Bean,加载至IOC)
- 未指定时,自动扫描
当前配置类所有同级及子级
的包路径TypeExcludeFilter
:自定义排除 SpringBoot 提供的扩展类AutoConfigurationExcludeFilter
:过滤会自动装配的配置类,避免重复
- 将当前配置类所在包保存在 BasePackages 的Bean中,供Spring内部使用
- 就是注册了一个保存当前配置类所在包的一个Bean
- 导入 AutoConfigurationImportSelector 实现了 DeferredImportSelector
- Spring内部在解析时,会调用其 getAutoConfigurationEntry()
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 从 spring.factories 中获得候选的自动装配类
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
// 排重
configurations = removeDuplicates(configurations);
// 根据 EnableAutoConfiguration 注解中属性,获取不需要自动装配的类名单
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
// 进行排除的类:
// 1. @EnableAutoConfiguration.exclude
// 2. @EnableAutoConfiguration.excludeName
// 3. spring.autoconfigure.exclude
checkExcludedClasses(configurations, exclusions);
// exclusions 也排除
configurations.removeAll(exclusions);
// 通过读取 spring.factories 进行过滤
// 1. OnBeanCondition
// 2. OnClassCondition
// 3. OnWebApplicationCondition
configurations = getConfigurationClassFilter().filter(configurations);
// 调用实现 AutoConfigurationImportListener 的 bean...
// 分别把候选的配置名单、排除的配置名单,传进去做扩展
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
-
每个SpringBoot应用,都会引入 spring-boot-autoconfigure
- 而 spring.factories 文件就在该包下面
-
spring.factories 文件是 KV 形式,多个 value 时用 , 隔开
- 文件中定义了关于 初始化、监听器 等信息
-
而真正使自动配置生效的 key 是 org.springframework.boot.autoconfigure.EnableAutoConfiguration
-
等同于 @Import({
-
# Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\ ...省略 org.springframework.boot.autoconfigure.websocket.WebSocketMessagingAutoConfiguration,\ org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration
-
})
-
-
每个 xxxAutoConfiguration 类都是容器中的一个组件,都加入到容器中,用它们来做自动配置
-
@EnabelAutoConfiguration 注解通过 @SpringBootApplication 被简介标记在 SpringBoot 的启动类上
- 在 SpringApplication.run(...) 方法内部,就会执行 selectImports() 方法
- 找到所有 JavaConfig 自动配置类的全限定名对应的 Class 并加载到 Spring IOC 容器中
- HttpEncodingAutoConfiguration:Http编码自动配置
- Spring 会给标记 @Configuration 的配置类创建 cglib动态代理
- 防止每次调用本类的@bean方法重复创建对象,Bean默认单例
- 启用可以在配置类设置属性对应的类
- 当 @Conditional 指定的条件成立,才给容器中添加组件,配置里面的内容才生效
@Conditional扩展注解作用 | (判断是否满足当前指定条件) |
---|---|
@ConditionalOnJava | 系统的java版本是否符合要求 |
@ConditionalOnBean | 容器中存在指定Bean; |
@ConditionalOnMissingBean | 容器中不存在指定Bean; |
@ConditionalOnExpression | 满足SpEL表达式指定 |
@ConditionalOnClass | 系统中有指定的类 |
@ConditionalOnMissingClass | 系统中没有指定的类 |
@ConditionalOnSingleCandidate | 容器中只有一个指定的Bean,或者这个Bean是首选Bean |
@ConditionalOnProperty | 系统中指定的属性是否有指定的值 |
@ConditionalOnResource | 类路径下是否存在指定资源文件 |
@ConditionalOnWebApplication | 当前是web环境 |
@ConditionalOnNotWebApplication | 当前不是web环境 |
@ConditionalOnJndi | JNDI存在指定项 |
- 配置文件中启用 debug = true
- @Configuration:标注为配置类,会被加载到IOC容器
- @ConditionalOnWebApplication:标注该配置类只有在Web环境下生效
- @ConditionOnClass:标注该配置类只有在项目中有CharacterEncodingFilter 才生效
- CharacterEncodingFilter:SpringMVC中解决乱码的过滤器
- @ConditionalOnProperty:标注该配置类只有在 spring.http.encoding.enabled = true 时才生效
- spring.http.encoding.enbaled 不存在配置也是生效的
- @EnbaleConfigurationProperties:将配置文件中值绑定的属性类加载到 IOC 容器
- @SpringBootApplication 注解上带有该配置
- 表示启用自动配置
- 对项目业务定义的bean和三方框架的bean做分组,方便后面排序
- 先处理项目中的Bean
- 再处理三方框架导入的自动配置Bean
- 这么做的意义,举例:
- mybatis 的 starter 导入了 SqlSessionFactory Bean
- Bean 上标注了 @ConditionOnBean 的条件
- 项目自定义了一个 SqlSessionFactory Bean
- 根据分组的加载顺序,就会优先加载项目自定义的 SqlSessionFactory
- 而在加载 starter 中的 SqlSessionFactory 时,就会根据 @ConditionOnBean 的条件决定不加载,采用项目自定义的 SqlSessionFactory
- mybatis 的 starter 导入了 SqlSessionFactory Bean
- KV形式的键值对
- 即加载上图示例中 org.springframework.boot.autoconfigure.EnableAutoConfiguration 对应的Bean集合
- spring-boot-autoconfigure 官方下的自动配置类就有127个(不同版本数量不一样)
- 对上步返回的项目最终有效自动配置类进行排序(只会对当前组里的Bean排序)
- WebMvcAutoConfiguration
- 创建 pom 项目 test-spring-boot-starter
- 创建子model spring-boot-starter-test
- 依赖 spring-boot-starter-test-autoconfiguration
- 空jar
- 创建子model spring-boot-starter-test-autoconfiguration
- 写个 IndexController Bean,放在 spring.factories
- mvn clean install 下载到本地Maven库
- 创建子model spring-boot-starter-test
- 业务项目依赖 spring-boot-starter-test
- 启动项目,访问 IndexController
- 这就是自定义starter、自动配置的基本流程
- @Component、@Service、@Controller.. 标注的类一定是能项目能扫描到的路径
- @ComponentScan 即项目扫描bean的路径
- @Import 可以导入项目扫描不到的类、还可以批量导入Bean