springboot启动分析(三)
@SpringBootApplication
主要是如下三个注解:
- SpringBootConfiguration
- EnableAutoConfiguration
- ComponentScan
@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 {
@SpringBootConfiguration
这个注解的核心就是@Configuration
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
}
@EnableAutoConfiguration
主要用了@Import注解
- 核心类:AutoConfigurationImportSelector
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
/**
* Exclude specific auto-configuration classes such that they will never be applied.
* @return the classes to exclude
*/
Class<?>[] exclude() default {};
/**
* Exclude specific auto-configuration class names such that they will never be
* applied.
* @return the class names to exclude
* @since 1.3.0
*/
String[] excludeName() default {};
}
@Import注解
Import注解一般和{@link Configuration}, {@link ImportSelector}, {@link ImportBeanDefinitionRegistrar}这些一起使用。
我们来看看官方解释:
- 用来import一个或者多个用@Configuration注解的class类。
- 可以用来导入ImportSelector、ImportBeanDefinitionRegistrar接口的实现类,参照AnnotationConfigApplicationContext#register
Import这个导入注解是自动装配的核心。
TIPS:注解的使用说明:
- @Target:这个用于说明注解使用的地方
- TYPE: 作用于类,接口,或者枚举
- FIELD: 作用于属性申明
- METHOD: 作用于方法的申明
- PARAMETER: 作用于参数申明
- 。。。。。
- @Retention:生效时间
- SOURCE:存在于源码阶段,编译阶段丢弃。
- CLASS:编译器会编译成二进制文件保存在class文件中,但是运行时虚拟机中不会保留,这是默认的方式。
- RUNTIME:class文件,运行时虚拟机中都会保留。
AutoConfigurationImportSelector
这个类实现类6个接口:
1、DeferredImportSelector
2、BeanClassLoaderAware
3、ResourceLoaderAware
4、BeanFactoryAware
5、EnvironmentAware
6、Ordered
说明下Aware的作用,这个中间件的作用就是容器的回调接口。实现了对应的Aware接口,能从spring容器中获取对应的资源。打个比方实现了BeanFactoryAware接口,能获取容器中加载所有类对象的beanFactory:ConfigurableListableBeanFactory。
DeferredImportSelector
实现了ImportSelector接口。这个实现类,在所有Configuration注解类执行完毕后运行。
这个里面有个核心的方法:selectImports
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
//加载所有的properties中的对象
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
//这个是获取EnableAutoConfigruation中的方法名
AnnotationAttributes attributes = getAttributes(annotationMetadata);
//获取所有的注解对象,方法里面用到了SpringFactoriesLoader对象
List<String> configurations = getCandidateConfigurations(annotationMetadata,
attributes);
//以下都是中间的一些处理过程,看流程的时候可以忽略。
configurations = removeDuplicates(configurations);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = filter(configurations, autoConfigurationMetadata);
fireAutoConfigurationImportEvents(configurations, exclusions);
//最后结果返回所有注解的@EnableAutoConfiguration实例。
return StringUtils.toStringArray(configurations);
}
在这里,我们看到在第二章解释中出现的ServletWebServerFactoryAutoConfiguration。这个就是加载jvm容器启动类的。前后呼应。通过这个自动化装配机制,来启动容器。
BeanClassLoaderAware
获取上下文的BeanClassLoader对象。
ResourceLoaderAware
实现这个接口,能获取容器中所有的资源的处理器。我们看下ResourceLoader有哪些方法:
Resource getResource(String location);
@Nullable
ClassLoader getClassLoader();
第一个方法就是获取资源对象。也就是所有的内外部加载的resource对象。这个对象能获取所有的资源信息。
第二个方法是获取加载ResourceLoader的ClassLoader对象。
BeanFactoryAware
获取ConfigurableListableBeanFactory对象。
EnvironmentAware
获取Environment对象。
Ordered
在Servlet启动加载对象的时候,数值越小,优先级越高。