前言:关于Spring Boot的介绍已有很多,笔者平时使用的也很多,但是一直都是停留在使用层面,平时也时常好奇Spring Boot的原理,如何做到自动配置的,今天刚好有空,就自建了个项目调试了下,大概窥探了下Spring Boot的内部原理,分享出来,有不对的地方麻烦一定指正一波。
一、入口
Java项目自然从main函数开始看起
/**
* @author fandong
*/
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args){
SpringApplication.run(DemoApplication.class, args);
}
}
内容很少,主要分为两个部分:
- @SpringBootApplication 注解
- SpringApplication.run(DemoApplication.class, args); 这个静态的run()
下面我们先简要看下 @SpringBootApplication注解,为后面分析run()方法做铺垫
二、@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 {}
前四个注解都是 平时自定义注解时常用的注解:
- @Target 标识此注解的作用类型
- @Retention 标识注解的生命周期
- @Documented Java doc 相关注解
- @Inherited 标识子类可继承
后三个注解是我们比较关心的也是和SpringBoot功能实现密切相关的注解
@ComponentScan:对应xml配置时的自动扫描功能,可以通过 basePackages指定扫描的目录,不指定的情况下,扫描注解作用类所在的包(即 启动类的所在的包,启动类放在根路径 则默认扫描根路径)
@SpringBootConfiguration:代码如下
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
}
继承了 @Configuration的功能,将当前类作为一个 配置Bean
@EnableAutoConfiguration:自动装配核心注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({EnableAutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
Class<?>[] exclude() default {};
String[] excludeName() default {};
}
- 在理解之前首先需要先了解下 @Import注解:具体参照这篇 https://blog.csdn.net/everyok/article/details/81350905,作用就是根据提供的value值构造Bean提交给容器
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Import { /** 仔细看这边内容 * {@link Configuration}, {@link ImportSelector}, {@link ImportBeanDefinitionRegistrar} * or regular component classes to import. */ Class<?>[] value(); }
参照注释,@Import的value有四种选择
- @AutoConfigurationPackage
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited //关注这一行 @Import({Registrar.class}) public @interface AutoConfigurationPackage { }
Registrar类是实现了 ImportBeanDefinitionRegistrar接口(参照上述@Import注解的说明)
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports { Registrar() { } public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { //注册了注解类即主类的包名 调试可以验证这点 AutoConfigurationPackages.register(registry, (new AutoConfigurationPackages.PackageImport(metadata)).getPackageName()); } public Set<Object> determineImports(AnnotationMetadata metadata) { return Collections.singleton(new AutoConfigurationPackages.PackageImport(metadata)); } }
-
EnableAutoConfigurationImportSelector 类,这是 @Import注解value的另外一种类型
//注意下继承关系 继承自 AutoConfigurationImportSelector public class EnableAutoConfigurationImportSelector extends AutoConfigurationImportSelector { public EnableAutoConfigurationImportSelector() { } protected boolean isEnabled(AnnotationMetadata metadata) { return this.getClass().equals(EnableAutoConfigurationImportSelector.class) ? (Boolean)this.getEnvironment().getProperty("spring.boot.enableautoconfiguration", Boolean.class, true) : true; } }
AutoConfigurationImportSelector 类中,主要关注 selectImports(AnnotationMetadata annotationMetadata)方法,代码如下
public String[] selectImports(AnnotationMetadata annotationMetadata) { if (!this.isEnabled(annotationMetadata)) { return NO_IMPORTS; } else { try { AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader); AnnotationAttributes attributes = this.getAttributes(annotationMetadata); //重点关注这一行的 getCandidateConfigurations方法 List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes); configurations = this.removeDuplicates(configurations); configurations = this.sort(configurations, autoConfigurationMetadata); Set<String> exclusions = this.getExclusions(annotationMetadata, attributes); this.checkExcludedClasses(configurations, exclusions); configurations.removeAll(exclusions); //依据 @ConditionalOnClass 和 forName 来筛选 configurations = this.filter(configurations, autoConfigurationMetadata); this.fireAutoConfigurationImportEvents(configurations, exclusions); return (String[])configurations.toArray(new String[configurations.size()]); } catch (IOException var6) { throw new IllegalStateException(var6); } } }
getCandidateConfigurations方法代码如下:
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { //关注loadFactoryNames方法 List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.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; }
loadFactoryNames代码如下:
public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) { String factoryClassName = factoryClass.getName(); try { //去 META-INF/spring.factories文件中读取给中需要自动配置的类名咯 Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories"); ArrayList result = new ArrayList(); while(urls.hasMoreElements()) { URL url = (URL)urls.nextElement(); Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url)); String factoryClassNames = properties.getProperty(factoryClassName); result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames))); } return result; } catch (IOException var8) { throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() + "] factories from location [" + "META-INF/spring.factories" + "]", var8); } }
META-INF/spring.factories 文件内容部分展示如下:
# Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\ org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\ org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\ org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\ org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\ org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\ org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration
下面举个Gson()自动装配的简单例子来说明。 Spring Boot会在 容器启动之初 将 启动类封装为 BeanDefinition交给容器,容器在启动阶段会处理BeanDefinition中包含的 @Import注解,将相关的类封装为 BeanDefinition交给容器,这样在 实例化阶段就可以自动装配相关实例。
首先我们引入 Gson的maven依赖
META-INF/spring.factories 文件中 GsonAutoConfiguration 的代码如下:
@Configuration
//注意这一行 当前环境中有Gson类文件 则执行, 如何判断呢, forName
@ConditionalOnClass({Gson.class})
public class GsonAutoConfiguration {
public GsonAutoConfiguration() {
}
@Bean
//注意这一行 当前环境中没有 Gson类实例 则执行
@ConditionalOnMissingBean
public Gson gson() {
return new Gson();
}
}
三、SpringApplication.run(DemoApplication.class, args)
说明:这是整个项目的起点,首先执行run方法,run方法中会执行上述讲的 @EnableAutoConfiguration的功能
run方法代码如下:
public static ConfigurableApplicationContext run(Object source, String... args) {
return run(new Object[]{source}, args);
}
public static ConfigurableApplicationContext run(Object[] sources, String[] args) {
//构建了 SpringApplication的实例,并调用实例的run方法
//SpringApplication.run(DemoApplication.class, args)
//这里的 sources 就是传进来的 DemoApplication.class 这个启动类对象
return (new SpringApplication(sources)).run(args);
}
先分析下 new SpringApplication(sources) 这个方法如何处理 sources
public SpringApplication(Object... sources) {
this.bannerMode = Mode.CONSOLE;
this.logStartupInfo = true;
this.addCommandLineProperties = true;
this.headless = true;
this.registerShutdownHook = true;
this.additionalProfiles = new HashSet();
//关注这个
this.initialize(sources);
}
private void initialize(Object[] sources) {
if (sources != null && sources.length > 0) {
//将 sources添加到实例属性中,供后面使用
this.sources.addAll(Arrays.asList(sources));
}
this.webEnvironment = this.deduceWebEnvironment();
this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = this.deduceMainApplicationClass();
}
实例run方法如下:
public ConfigurableApplicationContext run(String... args) {
//计时器 执行的时间
//日志 Started DemoApplication in 11.358 seconds 中时间的由来
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
FailureAnalyzers analyzers = null;
this.configureHeadlessProperty();
//获取各种监听器 通过监听器可以将容器(ApplicationContext)的状态 starting、prepareEnvironment、prepareContext、finished等
SpringApplicationRunListeners listeners = this.getRunListeners(args);
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//准备环境 获取各种自定义的、Jvm中的、系统中的配置
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
//在控制台打印 Logo,想要对Logo做手脚的研究下这个方法
Banner printedBanner = this.printBanner(environment);
//创建 容器 ApplicationContext实例
context = this.createApplicationContext();
//对 context 进行检查
new FailureAnalyzers(context);
//关注下这个方法 将 启动类注册到 ApplicationContext.BeanFactory.beanDefinitionMap中 下面会详细分析
this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
//关注这个方法,包含了容器的主要启动流程,下面会详细分析
this.refreshContext(context);
this.afterRefresh(context, applicationArguments);
listeners.finished(context, (Throwable)null);
stopWatch.stop();
if (this.logStartupInfo) {
// Started DemoApplication in 11.358 seconds 这个日志在这里打印的
(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
}
//返回 ApplicationContext实例,项目中需要这个实例的话可以保存下SpringApplication.run(DemoApplication.class, args)的返回值
return context;
} catch (Throwable var9) {
this.handleRunFailure(context, listeners, (FailureAnalyzers)analyzers, var9);
throw new IllegalStateException(var9);
}
}
1)、先调试下 this.prepareContext(context, environment, listeners, applicationArguments, printedBanner); 这个方法
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
context.setEnvironment(environment);
this.postProcessApplicationContext(context);
this.applyInitializers(context);
listeners.contextPrepared(context);
if (this.logStartupInfo) {
this.logStartupInfo(context.getParent() == null);
this.logStartupProfileInfo(context);
}
// 注册 项目的启动入参
context.getBeanFactory().registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);
}
// 这个sources 其实就是 启动类实例
Set<Object> sources = this.getSources();
Assert.notEmpty(sources, "Sources must not be empty");
//关注这个方法 检查启动类是否有 @Component注解,并构造对应的 BeanDefinition对象给 容器
this.load(context, sources.toArray(new Object[sources.size()]));
listeners.contextLoaded(context);
}
this.load(context, sources.toArray(new Object[sources.size()])); 方法代码如下
protected void load(ApplicationContext context, Object[] sources) {
if (logger.isDebugEnabled()) {
logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
}
//通过 BeanDefinitionLoader 实例来完成 检查、构造 BeanDefinition实例的工作
BeanDefinitionLoader loader = this.createBeanDefinitionLoader(this.getBeanDefinitionRegistry(context), sources);
if (this.beanNameGenerator != null) {
loader.setBeanNameGenerator(this.beanNameGenerator);
}
if (this.resourceLoader != null) {
loader.setResourceLoader(this.resourceLoader);
}
if (this.environment != null) {
loader.setEnvironment(this.environment);
}
//关注这个方法 包含了具体的逻辑
loader.load();
}
loader.load(); 方法代码如下
public int load() {
int count = 0;
Object[] var2 = this.sources;
int var3 = var2.length;
for(int var4 = 0; var4 < var3; ++var4) {
Object source = var2[var4];
//关注这一行 包含具体逻辑
count += this.load(source);
}
return count;
}
count += this.load(source); 方法代码如下
private int load(Object source) {
Assert.notNull(source, "Source must not be null");
if (source instanceof Class) {
// 匹配这个 if
return this.load((Class)source);
} else if (source instanceof Resource) {
return this.load((Resource)source);
} else if (source instanceof Package) {
return this.load((Package)source);
} else if (source instanceof CharSequence) {
return this.load((CharSequence)source);
} else {
throw new IllegalArgumentException("Invalid source type " + source.getClass());
}
}
return this.load((Class)source); 方法代码如下
private int load(Class<?> source) {
if (this.isGroovyPresent() && BeanDefinitionLoader.GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
BeanDefinitionLoader.GroovyBeanDefinitionSource loader = (BeanDefinitionLoader.GroovyBeanDefinitionSource)BeanUtils.instantiateClass(source, BeanDefinitionLoader.GroovyBeanDefinitionSource.class);
this.load(loader);
}
// 关注这个 isComponent 方法 递归分析注解
//其中一条检索路径为 @SpringBootApplication -> @SpringBootConfiguration -> @Configuration -> @Component
if (this.isComponent(source)) {
// 注册方法
this.annotatedReader.register(new Class[]{source});
return 1;
} else {
return 0;
}
}
从 this.annotatedReader.register(new Class[]{source}); 一路跟踪到如下方法
public void registerBean(Class<?> annotatedClass, String name, Class<? extends Annotation>... qualifiers) {
//将我们的启动类 包装为 BeanDefinition对象 下面会 完善相关的信息 Primary、LazyInit等
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
if (!this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
String beanName = name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry);
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
if (qualifiers != null) {
Class[] var7 = qualifiers;
int var8 = qualifiers.length;
for(int var9 = 0; var9 < var8; ++var9) {
Class<? extends Annotation> qualifier = var7[var9];
if (Primary.class == qualifier) {
abd.setPrimary(true);
} else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
} else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
// 最终注册
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
}
总结下 prepareContext 方法的工作: 检查启动类是否带了 @Component 注解, 将启动类包装为 BeanDefinition实例 并注册到容器中,位置在 context -> beanFactory -> beanDefinitionMap 中,调试可见, 这边是 Spring Boot的预先工作范围
2)、再来看下最为核心的 this.refreshContext(context); 方法,里面包含了容器启动的核心逻辑
一路跟踪找到最终的 refresh 方法,代码如下
public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
this.prepareRefresh();
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
this.prepareBeanFactory(beanFactory);
try {
this.postProcessBeanFactory(beanFactory);
//关注这个方法 包含了 @EnableAutoConfiguration 将需要的类包装为BeanDefinition提交给容器,以及扫描所有我们自己的 有@Component的类也会包装为BeanDefinition
//其中会处理 @Import注解
this.invokeBeanFactoryPostProcessors(beanFactory);
//扫描所有的 BeanDefinition 如果有 BeanPostProcessor类型的 则将其注册到容器,具体调用在 Bean实例化阶段,用以改变Bean的行为
this.registerBeanPostProcessors(beanFactory);
this.initMessageSource();
this.initApplicationEventMulticaster();
this.onRefresh();
this.registerListeners();
// Bean实例化 以及 BeanFactory的处理
this.finishBeanFactoryInitialization(beanFactory);
this.finishRefresh();
} catch (BeansException var9) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
}
this.destroyBeans();
this.cancelRefresh(var9);
throw var9;
} finally {
this.resetCommonCaches();
}
}
}
this.invokeBeanFactoryPostProcessors(beanFactory); 方法代码如下:
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
//关注这个方法
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, this.getBeanFactoryPostProcessors());
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean("loadTimeWeaver")) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, this.getBeanFactoryPostProcessors());这段代码很长,截取其中的关键方法如下
private static void invokeBeanDefinitionRegistryPostProcessors(Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
Iterator var2 = postProcessors.iterator();
while(var2.hasNext()) {
BeanDefinitionRegistryPostProcessor postProcessor = (BeanDefinitionRegistryPostProcessor)var2.next();
//关注这个方法
postProcessor.postProcessBeanDefinitionRegistry(registry);
}
}
postProcessor.postProcessBeanDefinitionRegistry(registry); 代码如下
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
int registryId = System.identityHashCode(registry);
if (this.registriesPostProcessed.contains(registryId)) {
throw new IllegalStateException("postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
} else if (this.factoriesPostProcessed.contains(registryId)) {
throw new IllegalStateException("postProcessBeanFactory already called on this post-processor against " + registry);
} else {
this.registriesPostProcessed.add(registryId);
//关注这个方法
this.processConfigBeanDefinitions(registry);
}
}
this.processConfigBeanDefinitions(registry); 部分方法如下
ConfigurationClassParser parser = new ConfigurationClassParser(this.metadataReaderFactory, this.problemReporter, this.environment, this.resourceLoader, this.componentScanBeanNameGenerator, registry);
Set<BeanDefinitionHolder> candidates = new LinkedHashSet(configCandidates);
HashSet alreadyParsed = new HashSet(configCandidates.size());
do {
// 处理 @Import注解
parser.parse(candidates);
parser.parse(candidates);方法中最重要的是如下方法
private void processDeferredImportSelectors() {
List<ConfigurationClassParser.DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;
this.deferredImportSelectors = null;
Collections.sort(deferredImports, DEFERRED_IMPORT_COMPARATOR);
Iterator var2 = deferredImports.iterator();
while(var2.hasNext()) {
ConfigurationClassParser.DeferredImportSelectorHolder deferredImport = (ConfigurationClassParser.DeferredImportSelectorHolder)var2.next();
ConfigurationClass configClass = deferredImport.getConfigurationClass();
try {
//关注此方法 收集需要用到的 import信息
String[] imports = deferredImport.getImportSelector().selectImports(configClass.getMetadata());
this.processImports(configClass, this.asSourceClass(configClass), this.asSourceClasses(imports), false);
} catch (BeanDefinitionStoreException var6) {
throw var6;
} catch (Throwable var7) {
throw new BeanDefinitionStoreException("Failed to process import candidates for configuration class [" + configClass.getMetadata().getClassName() + "]", var7);
}
}
}
String[] imports = deferredImport.getImportSelector().selectImports(configClass.getMetadata()); 收集import方法如下
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
//获取到前面说的 META-INF/spring.factories 下的所有配置类名称
List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
configurations = this.removeDuplicates(configurations);
configurations = this.sort(configurations, autoConfigurationMetadata);
Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
this.checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
//过滤 将不满足 @Conditional 注解要求的去除,采用了 二分法,主要是 反射 forName 构造 @ConditionalOnClass 要求的类, 成功即满足要求,失败则需要去除
configurations = this.filter(configurations, autoConfigurationMetadata);
this.fireAutoConfigurationImportEvents(configurations, exclusions);
return (String[])configurations.toArray(new String[configurations.size()]);
接下来就是 将符合要求的 通过 @AutoConfiguration @Import注解导入的各种 Configuration Bean 包装为 BeanDefinition,等待实例化的时候 调用 @Bean注解的方法生成Bean给 容器
总结下 refreshContext 的工作:其实就是对应了 Spring 容器的启动流程,扫描所有的 @Component注解标记的类,封装为BeanDefinition 到容器中,BeanDefinition中有 @Import等注解的,还要进一步处理, 这是 Spring容器的正常流程。但是为了做到自动装配,Spring Boot 在这之前,通过 prepareContext方法将标注了 @SpringBootApplication的启动类封装为 BeanDefinition添加到了容器中,这样在容器启动时 也就是 refreshContext方法中,会扫描所有的 @Import注解,将注解提供的类信息包装为BeanDefinition,而 @SpringBootApplication 注解上的 @Import注解提供的类恰恰是 META-INF/spring.factories 中的 校验过 @ConditionalOnClass 注解逻辑的 类,将满足当前环境要求的类封装为 BeanDefinition,这些类一般都是 工厂类,之后在 实例化阶段就可以自动实现相关类的实例化,也就是实现了 自动装配。
下面附上Spring容器启动流程
最后总结下 Spring Boot 主要启动流程:
prepareContext
首先将启动类封装为 BeanDefinition给容器
refreshContext
容器启动阶段(通过内置的 BeanFactoryPostProcessor 来完成以下 1、2的工作):
1、扫描所有的 @Component作用的类(直接或者间接作用)封装 BeanDefinition到容器中
2、处理 @Import等注解,将相关类同样 封装 BeanDefinition到容器中 (自动装配)
3、其它 自定义扩展的 BeanFactoryPostProcessor 实例 对 BeanDefinition 做出修改
Bean实例化阶段:
1、实例化Bean,有 @Autowired注解的 再去实例化对应的Bean并 注入
2、BeanFactory的处理,调用工厂方法生成Bean
3、BeanPostProcessor 对Bean实例做出修改,例如 生成代理类等
核心流程代码片段如下:
//关注下这个方法 将 启动类注册到 ApplicationContext.BeanFactory.beanDefinitionMap中 下面会详细分析
this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
//关注这个方法,包含了容器的主要启动流程,下面会详细分析
this.refreshContext(context);
//调用内置的和 自定义的 BeanFactoryPostProcessor 完成的功能包括:扫描并包装 BeanDefinition, 特殊注解如 @Import的处理
this.invokeBeanFactoryPostProcessors(beanFactory);
//扫描所有的 BeanDefinition 如果有 BeanPostProcessor类型的 则将其注册到容器,具体调用在 Bean实例化阶段,用以改变Bean的行为
this.registerBeanPostProcessors(beanFactory);
// Bean实例化 以及 BeanFactory的处理
this.finishBeanFactoryInitialization(beanFactory);