过几天公司培训,我这边整理了下PPT。顺便写了点代码,我放GitHub上了
对于 spring 框架,我们接触得比较多的应该是 spring mvc、 和 spring。而 spring 的核心在于 IOC(控制反转)和 DI (依赖注入)。而这些框架在使用的过程中会需要配置大量 的 xml,或者需要做很多繁琐的配置。 springboot 框架是为了能够帮助使用 spring 框架的开发 者快速高效的构建一个基于 spirng 框架以及 spring 生态 体系的应用解决方案。它是对“约定优于配置”这个理念下 的一个最佳实践。因此它是一个服务于框架的框架,服务 的范围是简化配置文件。
约定优于配置的体现主要是
1. maven 的目录结构
a) 默认有 resources 文件夹存放配置文件
b) 默认打包方式为 jar
2. spring-boot-starter-web 中默认包含 spring mvc 相关 依赖以及 内置的 tomcat 容器,使得构建一个 web 应用 更加简单
3. 默认提供 application.properties/yml 文件
4. 默认通过 spring.profiles.active 属性来决定运行环境时 读取的配置文件
5. EnableAutoConfiguration 默认对于依赖的 starter 进行 自动装载
现在目前应该是大多数互联网的主要配置方式,如果知道或者用过就可以不看下面的文字了。它是 JavaConfig 形式的基于 Spring IOC 容器的配置类使用的一种注解 ,因为SpringBoot 本质上就是一个 spring 应用,所以通过这个注解来加载 IOC 容器的配置是很正常的。所以在启动类 里面标注了@Configuration,意味着它其实也是一个 IoC 容器的配置类。传统意义上的 spring 应用都是基于 xml 形式来配置 bean 的依赖关系。然后通过 spring 容器在启动的时候,把 bean 进行初始化并且,如果 bean 之间存在依赖关系,则分析这 些已经在 IoC 容器中的 bean 根据依赖关系进行组装。 直到 Java5 中,引入了 Annotations 这个特性,Spring 框 架也紧随大流并且推出了基于 Java 代码和 Annotation 元 信息的依赖关系绑定描述的方式。也就是 JavaConfig。 从 spring3 开始,spring 就支持了两种 bean 的配置方式, 一种是基于 xml 文件方式、另一种就是 JavaConfig 任何一个标注了@Configuration 的 Java 类定义都是一个 JavaConfig 配置类。而在这个配置类中,任何标注了 @Bean 的方法,它的返回值都会作为 Bean 定义注册到 Spring 的 IOC 容器,方法名默认成为这个 bean 的 id
Enable 主机应该是在 JavaConfig 框架上更进一 步的完善,是的用户在使用 spring 相关的框架是,避免配 置大量的代码从而降低使用的难度 比如常见的一些 Enable 注解:EnableWebMvc,(这个注 解引入了 MVC 框架在 Spring 应用中需要用到的所有 bean); 比如说@EnableScheduling,开启计划任务的支持; 找到 EnableAutoConfiguration,我们可以看到每一个涉及 到 Enable 开头的注解,都会带有一个@Import 的注解。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
xxxx
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AsyncConfigurationSelector.class)
public @interface EnableAsync {
xxxx
}
EnableAutoConfiguration中也是个复合注解 包含
AutoConfigurationPackage。Import注解
import 注解是什么意思呢? 联想到 xml 形式下有一个
1. 第一种就是前面演示过的,基于普通 bean 或者带有 @Configuration 的 bean 进行诸如
2. 实现 ImportSelector 接口进行动态注入
3. 实现 ImportBeanDefinitionRegistrar 接口进行动态注入
2.1.1通过import注入其他配置类加载其他包下面的bean
@Import(OtherConfig.class)
@Configuration
public class SpringConfig {
@Bean
public DefaultBean defaultBean(){
return new DefaultBean();
}
}
@Configuration
public class OtherConfig {
//iff ...
//else ..
@Bean
public OtherBean otherBean(){
return new OtherBean();
}
}
2.1.2 import注入 xxxxImportSelector
我们来着这个类,是实现了 ImportSelector,也就是说所有实现类 ImportSelector接口的实现类,可以作为import注解的参数
AutoConfigurationImportSelector implements DeferredImportSelector 》DeferredImportSelector extends ImportSelector
public interface ImportSelector {
/**
* Select and return the names of which class(es) should be imported based on
* the {@link AnnotationMetadata} of the importing @{@link Configuration} class.
*/
String[] selectImports(AnnotationMetadata importingClassMetadata);
}
让我们来看下接口实现
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
//加载文件"META-INF/" + "spring-autoconfigure-metadata.properties"
//返回包装类,里面其实是kv
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
//返回SPI加载的bean实体。List beanNames
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,
annotationMetadata);
//返回数组后,就会托管到SPRIng容器中,具体可以看上面那个博客
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
//返回SPI加载的bean实体。List beanNames
protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
//返回EnableAutoConfiguration.class.name作为key
AnnotationAttributes attributes = getAttributes(annotationMetadata);
//SpringFactoriesLoader.loadFactoryNames传入 key,SpringFactoriesLoader查找说有classpath下的META-INF/spring.factories返回对应的全路径名称
List configurations = getCandidateConfigurations(annotationMetadata, attributes);
//去重
configurations = removeDuplicates(configurations);
//获取排除的类
Set exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
//过滤条件注解比如OnBeanCondition这种进行条件判断
configurations = filter(configurations, autoConfigurationMetadata);
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
这里面会加载对应的配置
2.1.3 ImportBeanDefinitionRegistrar 接口进行动态注入
ComponentScan 这个注解是大家接触得最多的了,相当 于 xml 配置文件中的
我们可以直接用这三个注解也可以启动 springboot 应用, 只是每次配置三个注解比较繁琐,所以直接用一个复合注 解更方便些。 然后仔细观察者三个注解,除了 EnableAutoConfiguration 可能稍微陌生一点,其他两个注解使用得都很多