
前面的梳理中已经将Spring的容器的创建、Bean的创建、BeanPostProcessor的使用、ApplicationListener的使用、代理模式梳理完成,其实以上的所有的梳理都是Spring的Bean声明周期的细节,现在从整体上分析一下Spring中Bean声明周期是如何实现的。
以下的分析会从容器的启动、注解如何加载Bean、创建BeanDefinition、容器的刷新(核心)、创建Bean、销毁Bean的链路梳理,从源头了解Bean的生命周期。
容器启动流程
容器启动流程就是我们平时使用SpringBoot的启动类,在启动类中都会有一段SpringApplication.run(DispatchAdapterApplication.class, args) 代码,这段代码就是启动Spring服务的调用。在这段代码中启动了Spring应用,那么其中又是如何启动Spring容器,并且启动过程中如何将Bean注入到容器中的呢?从源码中梳理整个过程。
容器启动流程:
- 创建应用上下文接口ConfigurableApplicationContext,该接口可以理解为是最顶级的接口,该接口中提供了设置Spring环境、设置BeanFactoryPostProcessor、ApplicationListener、注册Bean、销毁Bean的所有方法,该接口是提供给应用启动程序使用,并且主要使用在启动和关闭阶段。
//Spring启动实现类
public class SpringApplication {
//注解的方式注入类的实现
public static final String DEFAULT_CONTEXT_CLASS = "org.springframework.context."
+ "annotation.AnnotationConfigApplicationContext";
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
//创建AnnotationConfigApplicationContext实现类
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(
SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
//对AnnotationConfigApplicationContext的准备逻辑,设置环境、监听器等
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
//调用容器刷新逻辑
refreshContext(context);
//刷新之后的处理,开发者可以重写该方法做后续的处理
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
listeners.started(context);
callRunners(context, applicationArguments);
}
.....
return context;
}
protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
switch (this.webApplicationType) {
case SERVLET:
contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
break;
case REACTIVE:
contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
break;
default:
//默认会调用这个实例化AnnotationConfigApplicationContext
contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
}
}

最低0.47元/天 解锁文章
1810

被折叠的 条评论
为什么被折叠?



