SpringBoot
SpringBoot是Java应用的开发框架,基于Spring4.0设计,继承了Spring框架原有的优秀特性,还并通过简化配置来进一步优化了Spring应用的整个搭建和开发过程,SpringBoot通过集成大量的框架,很好的解决了依赖包版本冲突,以及引用不稳定性等问题
SpringBoot 特性
- 创建独立的Spring应用
- 内嵌Tomcat或Jetty等Servlet容器,应用打包后即可直接运行
- 提供一系列预设配置来简化配置
- 尽可能自动配置Spring容器与三方类库
- 提供可用于生产的特性,如度量、运行状况检查和外部化配置
- 不需要代码生成,不需要XML配置
自动装配
自动装配是为了从spring.factories文件中获取到对应需要进行自动装配的类,并生成相应的Bean对象,然后将它们交给spring容器来管理嘛,自动装配是 SpringBoot 的核心,我们只要引入一个 starter 组件依赖就能实现自动装配
依赖
org.springframework.boot
spring-boot-starter-parent
2.6.3
启动类
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
@SpringBootApplication
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
// 内容省略
}
由源码可知,@SpringBootApplication实际是由3个关键的注解组成
- @SpringBootConfiguration
- @EnableAutoConfiguration
- @ComponentScan
@SpringBootConfiguration
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
@Indexed
public @interface SpringBootConfiguration {
// 内容省略
}
由源码可知,@SpringBootConfiguration 实际上就是一个 @Configuration 注解,就是为了让当前类作为一个配置类交由 Spring 的 IOC 容器进行管理
@ComponentScan
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
// 内容省略
}
由源码可知,@ComponentScan 等价于在 xml 文件中配置 context:component-scan,SpringBoot 会默认扫描当前类所在的包及其子包中的所有标注了 @Component,@Service,@Controller 等注解的类
@EnableAutoConfiguration
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
// 内容省略
}
由源码可知,@EnableAutoConfiguration 是由 @AutoConfigurationPackage 与 @Import 组成的注解,而AutoConfigurationImportSelector正是自动装配的核心;AutoConfigurationImportSelector实现了顶层接口ImportSelector,在selectImports方法中,首先判断SpringBoot是否开启自动配置,如开启则进一步获取需要自动装配的类
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
AnnotationAttributes attributes = getAttributes(annotationMetadata);
List configurations = getCandidateConfigurations(annotationMetadata, attributes);
configurations = removeDuplicates(configurations);
Set exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = getConfigurationClassFilter().filter(configurations);
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
protected List getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
getBeanClassLoader());
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
+ "are using a custom packaging, make sure that file is correct.");
return configurations;
}
其中的重点就在SpringFactoriesLoader.loadFactoryNames这一行代码中
public final class SpringFactoriesLoader {
/**
* The location to look for factories.
* Can be present in multiple JAR files.
*/
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
private static final Log logger = LogFactory.getLog(SpringFactoriesLoader.class);
static final Map>> cache = new ConcurrentReferenceHashMap<>();
private SpringFactoriesLoader() {
}
至此已可以看出,为何SpringBoot的依赖中会存在.factories文件,loadFactoryNames 方法会去 META-INF/spring.factories 文件中根据 EnableAutoConfiguration 的全限定类名获取到我们需要导入的类,而 EnableAutoConfiguration 类的全限定类名为
org.springframework.boot.autoconfigure.EnableAutoConfiguration
@AutoConfigurationPackage
@AutoConfigurationPackage 注解会将添加该注解的类所在的 package 作为自动配置 package 进行管理,也就是说当SpringBoot应用启动时,默认会将启动类所在的package作为自动配置的package
总结
- SpringBoot 是基于 Spring 的框架
- SpringBoot 预置了许多依赖,并简化了 Spring 原有的配置,使开发更加简单快捷
- SpringBoot 通过 AutoConfigurationImportSelector 与 META-INF/spring.factories 省去了一些类的配置过程,实现了自动装配