springboot源码解析-管中窥豹系列之自动装配(九)

Springboot源码解析是一件大工程,逐行逐句的去研究代码,会很枯燥,也不容易坚持下去。

我们不追求大而全,而是试着每次去研究一个小知识点,最终聚沙成塔,这就是我们的springboot源码管中窥豹系列。

 简介

二、何为自动装配?

我们想用redis,直接引入spring-boot-starter-data-redis的依赖,配置加上就能用。

我们想用mongodb, 直接引入mongodb的依赖

我们想用缓存,直接引入cache的依赖

我们在:springboot源码解析-管中窥豹系列之web服务器(七) 里面想更换不同的web服务器,更换不同的依赖,那里也是用到自动装配

三、源码分析

我们从main方法所在类开始看:

import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class MyprojectApplication { public static void main(String[] args) { SpringApplication.run(MyprojectApplication.class, args); } }

这次不进main方法,我们看注解:@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 { ... }

我们看这个注解:@EnableAutoConfiguration

注意这个注解是在:spring-boot-autoconifgure依赖包里面

@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 {}; }

spring.boot.enableautoconfiguration:自动装配的开关,默认开

我们看这个:@Import(AutoConfigurationImportSelector.class)

springboot会加载@Import 和 继承ImportSelector的类 到bean集合里面

public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered { ... }

继承的各种Aware,我们之前说过:springboot源码解析-管中窥豹系列之aware(六)

Ordered:我们在之前排序那一节也说过:springboot源码解析-管中窥豹系列之排序(五)

ImportSelector是把继承的selectImports方法的返回数组转换成加载的bean

public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered { .... private static final String[] NO_IMPORTS = {}; @Override public String[] selectImports(AnnotationMetadata annotationMetadata) { if (!isEnabled(annotationMetadata)) { return NO_IMPORTS; } AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata); return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations()); } protected boolean isEnabled(AnnotationMetadata metadata) { if (getClass() == AutoConfigurationImportSelector.class) { return getEnvironment().getProperty(EnableAutoConfiguration.ENABLED_OVERRIDE_PROPERTY, Boolean.class, true); } return true; } .... }

先判断开关,没打开就返回空数组

getAutoConfigurationEntry() 拿到要加载成bean的对象

转换成数组返回

我们看看这个方法:getAutoConfigurationEntry()

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); }

其它行都是加工数据的,或者exlusions(排除),filter(过滤)

最重要的是:List configurations = getCandidateConfigurations(annotationMetadata, attributes);

我们看这个方法:getCandidateConfigurations

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; } protected Class<?> getSpringFactoriesLoaderFactoryClass() { return EnableAutoConfiguration.class; }

SpringFactoriesLoader.loadFactoryNames, 我们之前说过,是从spring.factories里面加载对应的class

这次要加载的class: EnableAutoConfiguration

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsfpwf.html