自动装配
@SpringBootApplication: 行这个类的main方法来启动SpringBoot应用
原理:
//设置当前注解可以标记在哪@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited//标注在某个类上,表示这是一个Spring Boot的配置类@SpringBootConfiguration@EnableAutoConfiguration@ComponentScan(excludeFilters = {@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })public @interface SpringBootApplication {
@SpringBootConfiguration:Spring Boot的配置类;标注在某个类上,表示这是一个Spring Boot的配置类;@Configuration:配置类上来标注这个注解;配置类 ----- 配置文件;配置类也是容器中的一个组件;@Component@EnableAutoConfiguration:开启自动配置功能;以前我们需要配置的东西,Spring Boot帮我们自动配置;@EnableAutoConfiguration告诉SpringBoot开启自动配置,会帮我们自动去加载 自动配置类@ComponentScan : 扫描包相当于在spring.xml 配置中<context:component-scan> 但是并没有指定basepackage,如果没有指定spring底层会自动扫描当前配置类所有在的包TypeExcludeFilterspringboot对外提供的扩展类, 可以供我们去按照我们的方式进行排除AutoConfigurationExcludeFilter排除所有配置类并且是自动配置类中里面的其中一个
EnableAutoConfiguration
@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited@AutoConfigurationPackage@Import(AutoConfigurationImportSelector.class)public @interface EnableAutoConfiguration {// 略}
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class) 关键点!
使用import完成的注册,自动配置,
AutoConfigurationImportSelector实现了DeferredImportSelectorSpring,
getAutoConfigurationEntry扫描,META-INFO/spring-factories文件中jar
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {if (!isEnabled(annotationMetadata)) {return EMPTY_ENTRY;}AnnotationAttributes attributes = getAttributes(annotationMetadata);// 从META-INF/spring.factories中获得候选的自动配置类List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);// 排重configurations = removeDuplicates(configurations);//根据EnableAutoConfiguration注解中属性,获取不需要自动装配的类名单Set<String> exclusions = getExclusions(annotationMetadata, attributes);// 根据:@EnableAutoConfiguration.exclude// @EnableAutoConfiguration.excludeName// spring.autoconfigure.exclude 进行排除checkExcludedClasses(configurations, exclusions);// exclusions 也排除configurations.removeAll(exclusions);// 通过读取spring.factories 中的OnBeanCondition\OnClassCondition\OnWebApplicationCondition进行过滤configurations = getConfigurationClassFilter().filter(configurations);// 这个方法是调用实现了AutoConfigurationImportListener 的bean.. 分别把候选的配置名单,和排除的配置名单传进去做扩展fireAutoConfigurationImportEvents(configurations, exclusions);return new AutoConfigurationEntry(configurations, exclusions);}
spring.factories文件格式key-value格式
# Initializersorg.springframework.context.ApplicationContextInitializer=\org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener# Application Listenersorg.springframework.context.ApplicationListener=\org.springframework.boot.autoconfigure.BackgroundPreinitializer# Auto Configuration Import Listenersorg.springframework.boot.autoconfigure.AutoConfigurationImportListener=\org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener# Auto Configuration Import Filtersorg.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\org.springframework.boot.autoconfigure.condition.OnBeanCondition,\org.springframework.boot.autoconfigure.condition.OnClassCondition,\org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition
获取对应的这个文件,加载对应的bean到BeanDefinitionMap接下来就是加载进容器了
所有自动配置类表:
https://docs.spring.io/spring-boot/docs/current/reference/html/auto-configuration-classes.html#appendix.auto-configuration-classes
@EnableAutoConfiguration注解通过@SpringBootApplication被间接的标记在了Spring Boot的启动类上。在SpringApplication.run(…)的内部就会执行selectImports()方法,找到所有JavaConfig自动配置类的全限定名对应的class,然后将所有自动配置类加载到Spring容器中
@Configuration(proxyBeanMethods = false) 判断是jdk代理还是cglib
| @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属性,控制台打印那些自动配置会生效

总结
就是如何加载不在scan包下的其他类
自定义starter
@Configuration@ConditionalOnWebApplication@ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurerAdapter.class})@ConditionalOnMissingBean({WebMvcConfigurationSupport.class})@AutoConfigureOrder(-2147483638)@AutoConfigureAfter({DispatcherServletAutoConfiguration.class, ValidationAutoConfiguration.class})public class WebMvcAutoConfiguration {@Import({WebMvcAutoConfiguration.EnableWebMvcConfiguration.class})@EnableConfigurationProperties({WebMvcProperties.class, ResourceProperties.class})public static class WebMvcAutoConfigurationAdapter extends WebMvcConfigurerAdapter {@Bean@ConditionalOnBean({View.class})@ConditionalOnMissingBeanpublic BeanNameViewResolver beanNameViewResolver() {BeanNameViewResolver resolver = new BeanNameViewResolver();resolver.setOrder(2147483637);return resolver;}}}
@Configuration //指定这个类是一个配置类@ConditionalOnXXX //指定条件成立的情况下自动配置类生效@AutoConfigureOrder //指定自动配置类的顺序@Bean //向容器中添加组件@ConfigurationProperties //结合相关xxxProperties来绑定相关的配置@EnableConfigurationProperties //让xxxProperties生效加入到容器中自动配置类要能加载需要将自动配置类,配置在META-INF/spring.factories中org.springframework.boot.autoconfigure.EnableAutoConfiguration=\org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
启动器
- 启动器(starter)是一个空的jar文件,仅仅提供辅助性依赖管理,这些依赖可能用于自动装配或其他类库。
- 需要专门写一个类似spring-boot-autoconfigure的配置模块
- 用的时候只需要引入启动器starter,就可以使用自动配置了
命名规范
官方命名规范
- 前缀:spring-boot-starter-
- 模式:spring-boot-starter-模块名
- 举例:spring-boot-starter-web、spring-boot-starter-jdbc
自定义命名空间
- 后缀:-spring-boot-starter
- 模式:模块-spring-boot-starter
- 举例:mybatis-spring-boot-starter
两个模块
- starter,是一个空的jar包
- autoconfigurer,写实现逻辑的bean
1:先创建starter 的pom
<dependencies><!--引入autoconfigure--><dependency><groupId>com.tulingxueyuan.springboot</groupId><artifactId>tulingxueyuan-spring-boot-autoconfigure</artifactId><version>0.0.1-SNAPSHOT</version></dependency><!--如果当前starter 还需要其他的类库就在这里引用--></dependencies>
2:autoconfigurer的pom
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--‐导入配置文件处理器,配置文件进行绑定就会有提示--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional></dependency></dependencies>
在configurateion写对应的bean
再创建spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.starter.tulingxueyuan.HelloAutoConfitguration
然后本地按照就可以使用了
测试
新建个项目
引入我们写的stare
<dependency><groupId>com.tulingxueyuan.springboot</groupId><artifactId>tulingxueyuan-spring-boot-starter</artifactId><version>0.0.1-SNAPSHOT</version></dependency>
就ok 啦
@ import的使用
把不在扫描范围内的bean导入
@Group 分组,利用分组,影响分组的实现顺序???
@DeferedImportSelector
扫描spring.factores文件的bean
过滤判断哪些类会生效,哪些不会,会有一个过滤
配置exclude排除不要的
BeanDefinitionMap:存储解析的bean定义
spring boot 2.0默认是CGlib动态代理的
@ConditionOnBean的含义:
自动配置,怎么把第三方的bean导入的。
启动原理
最终把spring.factories的配置加载进来,
加载进beanDefinitionMap,提供使用提供很多默认的bean使用,可以扩展,自定义
如何定制自己的配置类加载
在自己的项目加一个META-INF/spring.factories
指向自己的注解方法
maven
@ConditionOnClass失效,
starter的用处
把相关配置,加载进来,
加载对应的额配置
@EnableConfigurationProperties吧配置注册成bean
通过bean的后置处理器加载bean 
