springboot已经是目前java最主流的开发框架。springboot的四大组件分别是:starter、autoconfigure、CLI和actuator。
``
自动装配(autoconfigure)
自动装配可以说是springboot最核心的功能,大大方便了开发人员在开发中的重复工作。那么自动装配的原理是什么呢?
springboot的启动类如下:
@SpringBootApplication
public class Test001Application {
public static void main(String[] args) {
SpringApplication.run(Test001Application.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 {
@ComponentScan
这个注解,从名字上看就能知道是扫描的注解,默认扫描当前类下的package。
@EnableAutoConfiguration
开启自动装配功能
@SpringBootConfiguration
标识这是一个springboot的配置类
以上主要的还是@EnableAutoConfiguration,其代码如下
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
Class<?>[] exclude() default {};
String[] excludeName() default {};
}
这里来看,主要还是看@AutoConfigurationPackage
(自动配置包)和@Import(AutoConfigurationImportSelector.class)
(给IOC容器导入组件)这两个注解。
@AutoConfigurationPackage
代码如下
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({Registrar.class})
public @interface AutoConfigurationPackage {
String[] basePackages() default {};
Class<?>[] basePackageClasses() default {};
}
这个基本上就看 Registrar.class了
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
Registrar() {
}
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
AutoConfigurationPackages.register(registry, (String[])(new AutoConfigurationPackages.PackageImports(metadata)).getPackageNames().toArray(new String[0]));
}
public Set<Object> determineImports(AnnotationMetadata metadata) {
return Collections.singleton(new AutoConfigurationPackages.PackageImports(metadata));
}
}
这是一个AutoConfigurationPackages
的静态内部类,其中registerBeanDefinitions方法就是将@SpringbootApplication
的所在package下的组件扫描到IOC容器中。这里与@ComponentScan
的扫描的类不同,这里主要扫描@Entity的类。
AutoConfigurationImportSelector.class
这里主要的方法是
@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<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
configurations = removeDuplicates(configurations);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = getConfigurationClassFilter().filter(configurations);
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> 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;
}
这里可以看到最终调用还是List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),getBeanClassLoader());
这行代码。这里的意思就是直接调用springFactoryLoader去加载相应的内容。
public final class SpringFactoriesLoader {
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
SpringFactoriesLoader就是去加载META-INF/spring.factories的内容,该文件的内容就是key-value的格式。
org.springframework.boot.env.PropertySourceLoader=\
org.springframework.boot.env.PropertiesPropertySourceLoader,\
org.springframework.boot.env.YamlPropertySourceLoader
# Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener
# Error Reporters
org.springframework.boot.SpringBootExceptionReporter=\
org.springframework.boot.diagnostics.FailureAnalyzers
这里的两个参数getSpringFactoriesLoaderFactoryClass()
是对应key的类型,getBeanClassLoader()
是获取key需要的classLoader。
Starter
现在基本上,开发人员在开发的时候需要引入各种包时,基本都是用starter来导入。例如
<dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.0</version> </dependency>
看起源码,在pom.xml中发现,其实已经将需要的组件都引入了。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot</artifactId>
<version>2.1.0</version>
</parent>
<artifactId>mybatis-spring-boot-starter</artifactId>
<name>mybatis-spring-boot-starter</name>
<properties>
<module.name>org.mybatis.spring.boot.starter</module.name>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
</dependency>
</dependencies>
</project>
其中,需要看一下
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-autoconfigure</artifactId>
</dependency>
这里发现有个spring.factories文件。
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.mybatis.spring.boot.autoconfigure.MybatisLanguageDriverAutoConfiguration,\
org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
这里就是上面说的自动装配了。
CLI
以下是Spring Boot CLI的功能
- 它提供了一个从命令提示符运行和测试Spring Boot Application的接口。
- 它在内部使用Spring Boot Starter和Spring Boot AutoConfigurate组件来解决所有依赖关系并执行应用程序。
- 它包含Groovy编译器和Grape Dependency Manager。
- 它支持Groovy脚本,无需外部Groovy安装。
- 它添加了Spring Boot默认值并自动解决所有依赖项
actuator
Actuator是Springboot提供的用来对应用系统进行自省和监控的功能模块,借助于Actuator开发者可以很方便地对应用系统某些监控指标进行查看、统计等