自动装配
@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底层会自动扫描当前配置类所有在的包
TypeExcludeFilter
springboot对外提供的扩展类, 可以供我们去按照我们的方式进行排除
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格式
# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.autoconfigure.BackgroundPreinitializer
# Auto Configuration Import Listeners
org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\
org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener
# Auto Configuration Import Filters
org.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})
@ConditionalOnMissingBean
public 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