0、环境搭建
1、个人配置2.4.3的boot版本
2、下载工具
在方法上按住ctrl+q即可汉化注释,翻译的还行。
3、上一步下一步跳转快捷键设置
使用了较多的经典设计模式,继承关系比较复杂,容易花了眼,需要设置快捷键回到光标的上一个位置。
4、有的方法没有实现,需要查看其继承关系,在其类上使用ctrl+alt+b
1、构造方法
点击启动类的run方法,跳转到
SpringApplication.java
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return run(new Class<?>[] { primarySource }, args);
}
再点击里边的run方法,跳转到
SpringApplication.java
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return new SpringApplication(primarySources).run(args);
}
SpringApplication类的对象时由run方法来完成实例化处理的,而后对于当前的开发者来讲首先要关注的就是这个类的构造方法的定义了。
SpringApplication.java
public SpringApplication(Class<?>... primarySources) {
this(null, primarySources);
}
跳转到
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");//断言检查
//将传递过来的程序启动类的class对象 按照顺序保存在一个集合之中,LinkedHashSet就是保证顺序的。
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
this.webApplicationType = WebApplicationType.deduceFromClasspath();
//初始化自动装配加载的bean
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
//因为传递过来的是一个源,所以需要找到真正的主类
this.mainApplicationClass = deduceMainApplicationClass();
}
第二个参数的泛型,传递到现在实质上就是我们自建的启动类。
ResourceLoader:获取资源加载器(目的是加载我们的classPath/文件/网络资源/)
Private Set<Class<?>> primarySources;(所有的类的加载源)
Private WebApplicationType webApplicationType;(web应用类型)
Private List<BootStrap> bootstraps;(获取类加载器的配置)
Private Class<?> mainApplicationClass;(获取程序的主类)
private Class<?> deduceMainApplicationClass() {
try {
StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
for (StackTraceElement stackTraceElement : stackTrace) {
if ("main".equals(stackTraceElement.getMethodName())) {
return Class.forName(stackTraceElement.getClassName());
}
}
}
catch (ClassNotFoundException ex) {
// Swallow and continue
}
return null;
}
分析程序的应用主类:
根据整个类的结构来对程序进行分析,如果发现有主方法存在,则直接返回该类的class对象,最终获取到了我们程序的应用主类。这样就是传入再多的配置类,也不会影响。
WebApplicationType.java
ackage org.springframework.boot;
import org.springframework.util.ClassUtils;
public enum WebApplicationType {
NONE,//这个应用不能运行,程序没有执行。
SERVLET, //采用传统的webServlet运行
REACTIVE; //采用响应式变成模式运行
private static final String[] SERVLET_INDICATOR_CLASSES = { "javax.servlet.Servlet",
"org.springframework.web.context.ConfigurableWebApplicationContext" };
private static final String WEBMVC_INDICATOR_CLASS = "org.springframework.web.servlet.DispatcherServlet"; //springmvc的启动类
private static final String WEBFLUX_INDICATOR_CLASS = "org.springframework.web.reactive.DispatcherHandler";//Reactor的启动类
private static final String JERSEY_INDICATOR_CLASS = "org.glassfish.jersey.servlet.ServletContainer";
private static final String SERVLET_APPLICATION_CONTEXT_CLASS = "org.springframework.web.context.WebApplicationContext";
private static final String REACTIVE_APPLICATION_CONTEXT_CLASS = "org.springframework.boot.web.reactive.context.ReactiveWebApplicationContext";
static WebApplicationType deduceFromClasspath() {
if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
&& !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
return WebApplicationType.REACTIVE; //采用Reactive的模式运行
}
for (String className : SERVLET_INDICATOR_CLASSES) {
if (!ClassUtils.isPresent(className, null)) {
return WebApplicationType.NONE;
}
}
return WebApplicationType.SERVLET; //采用的是servlet的模式
}
static WebApplicationType deduceFromApplicationContext(Class<?> applicationContextClass) {
if (isAssignable(SERVLET_APPLICATION_CONTEXT_CLASS, applicationContextClass)) {
return WebApplicationType.SERVLET;
}
if (isAssignable(REACTIVE_APPLICATION_CONTEXT_CLASS, applicationContextClass)) {
return WebApplicationType.REACTIVE;
}
return WebApplicationType.NONE;
}
private static boolean isAssignable(String target, Class<?> type) {
try {
return ClassUtils.resolveClassName(target, null).isAssignableFrom(type);
}
catch (Throwable ex) {
return false;
}
}
}
这个类会给你一个最终的运行方式,通过我本类提供的一系列方法进行各种的逻辑判断,返回出你的运行模式。
SpringBoot应用程序开发可以有两种主要的处理形式,一种是基于传统的WebServlet编程实现的,另一种是基于Reactive响应式编程实现的。
WebServlet的开发:
Reactive的开发:
为了能够区分出不同的运行模式,就创建了“WebApplicationType”的枚举类型。
在springApplication构造方法里边有一个最为重要的方法
this.bootstrappers = new ArrayList(this.getSpringFactoriesInstances(Bootstrapper.class));
这个方法的主要功能是进行所有加载器的加载(“META-INF/spring.factories”)
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
return this.getSpringFactoriesInstances(type, new Class[0]);
}
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
//获取类加载器
ClassLoader classLoader = this.getClassLoader();
//类加载
Set<String> names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
//注册bean
List<T> instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
获取类加载器:resourceLoader就是获取classpath下的类加载器的资源。
public ClassLoader getClassLoader() {
return this.resourceLoader != null ? this.resourceLoader.getClassLoader() : ClassUtils.getDefaultClassLoader();
}
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
ClassLoader classLoaderToUse = classLoader;
if (classLoader == null) {
classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
}
String factoryTypeName = factoryType.getName();
return (List)loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());
}
进行类的加载。
private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes,
ClassLoader classLoader, Object[] args, Set<String> names) {
List<T> instances = new ArrayList<>(names.size());
for (String name : names) {
try {
Class<?> instanceClass = ClassUtils.forName(name, classLoader);
Assert.isAssignable(type, instanceClass);
Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);
T instance = (T) BeanUtils.instantiateClass(constructor, args);
instances.add(instance);
}
catch (Throwable ex) {
throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, ex);
}
}
return instances;
}
//注册bean
通过以上的分析,SpringApplication类中的构造方法主要是完成了如下的几件事情:
·获取ResourceLoad接口实例:为了便于类加载操作,获取类加载器;(可以尝试输出一下类加载器,除了java中的类加载器之外呢,还有大量spring自己定义的加载器)
·获取所有的主源类:这些主源类只有一个是springboot自己完成的。
·会自动分析当前的运行模式是servlet还是reactive。
·获取所有的类加载器,(通过我们的autoconfiguration配置的和starter)
·初始化所有的bean对象,并且自动进行我们的bean对策
·初始化所有的监听。
2、run()
在整个的SpringBoot里边除了使用SpringApplication进行构造化之外,最重要的一项就是run方法了,最终可以实现的所有相关核心处理全部都在这个方法中配置了。
SpringApplication.run(PansdApplication.class, args);
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return run(new Class<?>[] { primarySource }, args);
}
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return new SpringApplication(primarySources).run(args);
}
public ConfigurableApplicationContext run(String... args) {
//任务启动计时操作
StopWatch stopWatch = new StopWatch();
stopWatch.start();
//创建springboot类加载上下文环境,bootstraps的所有的factories的所有类加载器
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
//增加一个系统属性(增加了多个配置项)
configureHeadlessProperty();
//*获取并启动全部的监听器
SpringApplicationRunListeners listeners = getRunListeners(args);
//启动全部的监听
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//设置环境(profile的配置)
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
configureIgnoreBeanInfo(environment);
//打印banner信息
Banner printedBanner = printBanner(environment);
//创建应用上下文
context = createApplicationContext();
//启动应用上下文
context.setApplicationStartup(this.applicationStartup);
prepareContext(bootstrapContext, 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);
}
catch (Throwable ex) {
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
return context;
}
private SpringApplicationRunListeners getRunListeners(String[] args) {
Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
return new SpringApplicationRunListeners(logger,
getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args),
this.applicationStartup);
}
void starting(ConfigurableBootstrapContext bootstrapContext, Class<?> mainApplicationClass) {
doWithListeners("spring.boot.application.starting", (listener) -> listener.starting(bootstrapContext),
(step) -> {
if (mainApplicationClass != null) {
step.tag("mainApplicationClass", mainApplicationClass.getName());
}
});
}
EventPublishingRunListener。Java
看到其重写类,实现整个监听事件的启动。
@Override
public void starting(ConfigurableBootstrapContext bootstrapContext) {
this.initialMulticaster
.multicastEvent(new ApplicationStartingEvent(bootstrapContext, this.application, this.args));
}
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
// Create and configure the environment
ConfigurableEnvironment environment = getOrCreateEnvironment();
configureEnvironment(environment, applicationArguments.getSourceArgs());
ConfigurationPropertySources.attach(environment);
listeners.environmentPrepared(bootstrapContext, environment);
DefaultPropertiesPropertySource.moveToEnd(environment);
configureAdditionalProfiles(environment);
bindToSpringApplication(environment);
if (!this.isCustomEnvironment) {
environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
deduceEnvironmentClass());
}
ConfigurationPropertySources.attach(environment);
return environment;
}
Profile的配置
onfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
public interface ConfigurableEnvironment extends Environment, ConfigurablePropertyResolver {
public interface Environment extends PropertyResolver {
String[] getActiveProfiles();
protected ConfigurableApplicationContext createApplicationContext() {
return this.applicationContextFactory.create(this.webApplicationType);
}
ApplicationContextFactory.java
ConfigurableApplicationContext create(WebApplicationType webApplicationType);
就在这里边注册bean容器了。
通过以上的程序执行分析,所有在springboot之中的容器的启动都是通过了run()实现的,而run()在实现处理的时候一定会自动启动Spring容器(SpringBoot需要Spring容器支持),同时对于所有存在的环境的解析,也是通过此方法完成的,包括一系列的配置。
3、SpringBoot启动内置的web容器
Springboot 应用一旦启动之后,实际上都会启动内置的应用容器,包括jetty,tomcat,undertow(像WebLogic,WebSpere是不会使用的,因为是收费的)
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
//所有的上下文环境初始化完成
context = createApplicationContext();
//应用启动
context.setApplicationStartup(this.applicationStartup);
prepareContext(bootstrapContext, 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);
}
catch (Throwable ex) {
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
return context;
}
如果要是想启动我们内置的web容器,本次观察此方法。
context = createApplicationContext();
protected ConfigurableApplicationContext createApplicationContext() {
return this.applicationContextFactory.create(this.webApplicationType);
}
private ApplicationContextFactory applicationContextFactory = ApplicationContextFactory.DEFAULT;
容器的启动主要依靠的是ApplicationContextFactory的实例,而后打开这个类的default的配置。
@FunctionalInterface
public interface ApplicationContextFactory {
//默认的全局常量;
ApplicationContextFactory DEFAULT = (webApplicationType) -> {
try {
//Switch判断;一般是枚举类型
switch (webApplicationType) {
case SERVLET:
return new AnnotationConfigServletWebServerApplicationContext();
case REACTIVE:
return new AnnotationConfigReactiveWebServerApplicationContext();
default:
return new AnnotationConfigApplicationContext();
}
}
catch (Exception ex) {
throw new IllegalStateException("Unable create a default ApplicationContext instance, "
+ "you may need a custom ApplicationContextFactory", ex);
}
};
ConfigurableApplicationContext create(WebApplicationType webApplicationType);
static ApplicationContextFactory ofContextClass(Class<? extends ConfigurableApplicationContext> contextClass) {
return of(() -> BeanUtils.instantiateClass(contextClass));
}
static ApplicationContextFactory of(Supplier<ConfigurableApplicationContext> supplier) {
return (webApplicationType) -> supplier.get();
}
}
这是一个函数式接口,是springboot提供的。Org.springframework.boot,而不是spring。
在使用Default内置的实例化对象创建应用的时候,会判断当前的应用类型是servlet还是reactive。
返回了”AnnotationConfigServletWebServerApplicationContext”对象;
public AnnotationConfigServletWebServerApplicationContext() {
//读取注解配置的bean
this.reader = new AnnotatedBeanDefinitionReader(this);
//读取classpath配置的扫描的bean
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
又回到了springboot的源代码
org.springframework.boot.web.servlet.context;
先看是无参构造;
所有的启动上下文环境初始化完成之后,那么随后就要进行最终的启动处理了,而在run方法里边通过一下的”context.setApplicationStartup(this.applicationStartup);”实现了应用的启动,于是来观察这个方法的源代码。
oid setApplicationStartup(ApplicationStartup var1);
需要说明的是,这个是
public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable {
是个接口的方法,所以要找到其实现的子类。Ctrl alt b 看看这个方法的实现。
有两个实现:
第一个:抽象类
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
public void setApplicationStartup(ApplicationStartup applicationStartup) {
Assert.notNull(applicationStartup, "applicationStartup should not be null");
this.applicationStartup = applicationStartup;
}
第二个:继承了抽象类
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
p@Override
public void setApplicationStartup(ApplicationStartup applicationStartup) {
super.setApplicationStartup(applicationStartup);
this.beanFactory.setApplicationStartup(applicationStartup);
}
最重要实现的就是这个。
public void setApplicationStartup(ApplicationStartup applicationStartup) {
Assert.notNull(applicationStartup, "applicationStartup should not be null");
this.applicationStartup = applicationStartup;
}
看了下,都没啥用出。此时扒不出来了,看来思路错了。
看第一个抽象类,实现了ConfigurableApplicationContext 这个接口。
看看第一个的实现类。有
ServletWebServerApplicationContext.java
private static final Log logger = LogFactory.getLog(ServletWebServerApplicationContext.class);
//servlet的注册名称
public static final String DISPATCHER_SERVLET_NAME = "dispatcherServlet";
//是一个接口,规定了web应用的启动,停止,端口,servletconcig
private volatile WebServer webServer;
private ServletConfig servletConfig;
private String serverNamespace;
public ServletWebServerApplicationContext() {}
//创建web服务
private void createWebServer() {
//获取webserver的应用
WebServer webServer = this.webServer;
//后去servlet上下文
ServletContext servletContext = getServletContext();
if (webServer == null && servletContext == null) {//上下文为空
StartupStep createWebServer = //应用启动
this.getApplicationStartup().start("spring.boot.webserver.create");
//获取webserver的工厂类型
ServletWebServerFactory factory = getWebServerFactory();
//定义标签
createWebServer.tag("factory", factory.getClass().toString());
this.webServer = factory.getWebServer(getSelfInitializer());
//创建完成
createWebServer.end();
getBeanFactory().registerSingleton("webServerGracefulShutdown",
new WebServerGracefulShutdownLifecycle(this.webServer));
getBeanFactory().registerSingleton("webServerStartStop",
new WebServerStartStopLifecycle(this, this.webServer));
}
else if (servletContext != null) {
try {
getSelfInitializer().onStartup(servletContext);
}
catch (ServletException ex) {
throw new ApplicationContextException("Cannot initialize servlet context", ex);
}
}
initPropertySources();
}
随后需要观察的就是这样一个接口类型了。
ServletWebServerFactory
@FunctionalInterface
public interface ServletWebServerFactory {
WebServer getWebServer(ServletContextInitializer... initializers);
}
是一个接口,需要观察该接口可能存在的子类:
这个方法是不是有点熟悉呢?
public abstract class AbstractServletWebServerFactory extends AbstractConfigurableWebServerFactory
implements ConfigurableServletWebServerFactory {
这时又看到了更加希望看到的现象:
为了便于管理(适配器模式),提供有一个AbstractServletWebServerFactory抽象子类,而这个抽象子类提供有三个应用子类,
1、jetty容器:
package org.springframework.boot.web.embedded.jetty;
public class JettyServletWebServerFactory extends AbstractServletWebServerFactory
implements ConfigurableJettyWebServerFactory, ResourceLoaderAware {
2、Tomcat容器:
package org.springframework.boot.web.embedded.tomcat;
public class TomcatServletWebServerFactory extends AbstractServletWebServerFactory
implements ConfigurableTomcatWebServerFactory, ResourceLoaderAware {
3、Undertow容器:
package org.springframework.boot.web.embedded.undertow;
public class UndertowServletWebServerFactory extends AbstractServletWebServerFactory
implements ConfigurableUndertowWebServerFactory, ResourceLoaderAware {
4、容器启动类的refresh()
在SpringApplication.run方法之中呢除了可以实现所有相关的容器的环境配置之外,还存在有一个刷新的方法,而这个刷新的处理方法呢就是本次所需要分析的步骤了,因为这个刷新的方法和springboot有直接的关系。
ublic ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
prepareContext(bootstrapContext, 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);
}
catch (Throwable ex) {
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
return context;
}
refreshContext(context);
private void refreshContext(ConfigurableApplicationContext context) {
if (this.registerShutdownHook) { //销毁的回调处理
try {
context.registerShutdownHook();
}
catch (AccessControlException ex) {
// Not allowed in some environments.
}
}
refresh((ApplicationContext) context);
}
@Deprecated //不建议你使用了
protected void refresh(ApplicationContext applicationContext) {
Assert.isInstanceOf(ConfigurableApplicationContext.class, applicationContext);
refresh((ConfigurableApplicationContext) applicationContext);
}
protected void refresh(ConfigurableApplicationContext applicationContext) {
applicationContext.refresh();
}
这个可以使用了。
好像又有点繁琐了:
package org.springframework.context;
public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable {
void refresh() throws BeansException, IllegalStateException;
分析其实现的继承逻辑关系;
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {
package org.springframework.boot.web.servlet.context;
public class ServletWebServerApplicationContext extends GenericWebApplicationContext
implements ConfigurableWebServerApplicationContext {
观察下这里边的refresh();
@Override
public final void refresh() throws BeansException, IllegalStateException {
try {
super.refresh();
}
catch (RuntimeException ex) {
WebServer webServer = this.webServer;
if (webServer != null) {
webServer.stop();
}
throw ex;
}
}
这里边的有个父类的刷新方法,先看父类的:
package org.springframework.context.support;
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
//上下文刷新前的准备操作
preepareRefresh();
//告诉子类刷新内部bean工厂
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
prepareBeanFactory(beanFactory);
try {
//上边的方法注册完成了之后,这里开启springboot容器启动相关的处理了。
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
//进行bean注册
invokeBeanFactoryPostProcessors(beanFactory);
//bean注册的拦截
registerBeanPostProcessors(beanFactory);
//bean的注册完成
beanPostProcess.end();
//可以自动配置消息处理
initMessageSource();
//时间广播处理
initApplicationEventMulticaster();
//做一些特殊bean的初始化操作
onRefresh();
//坐监听的注册
registerListeners();
//完成此上下文的 bean 工厂的初始化,初始化所有剩余的单例 bean。
finishBeanFactoryInitialization(beanFactory);
//结束刷新
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
//出现了错误,销毁所有的bean
destroyBeans();
//取消刷新操作
cancelRefresh(ex);
throw ex;
}
finally {
//重置缓冲区,所有的bean都在内存中保存,虽然是单例的,但是也在内存中保存了。
resetCommonCaches();
contextRefresh.end();
}
}
}
实质上最终与SpringBoot有关的大部分的处理环境上实际上都在此方法中进行了处理。
看下上边的准备处理:
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
//类加载
beanFactory.setBeanClassLoader(getClassLoader());
if (!shouldIgnoreSpel) {
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
}
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
//配置bean的回调处理,这里加载完成了
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
beanFactory.ignoreDependencyInterface(ApplicationStartup.class);
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
//这里开始注册处理
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// Register early post-processor for detecting inner beans as ApplicationListeners.
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (!NativeDetector.inNativeImage() && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// Register default environment beans.
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
}
}
总结:
最终完成整个初始化操作之后,可以由refresh可以不断对整个环境进行监听,refresh也是在容器启动的时候进行调用,配置呢可以通过refresh进行动态的加载以及容器的刷新处理。
4、后续及其说明
1、文档根据白嫖b站视频(李兴华老师的springboot2.x)自己整理而成;
2、由于在文档上标记的颜色网站的代码框中不显示,造成阅读麻烦,后续文档会上传至gitee