SpringBoot 源码分析(一)
方法入口
//这个注解很重要,后面再来看它,先过代码
@SpringBootApplication
public class Application {
public static void main(String[] args) {
//跟进去
SpringApplication.run(AdminApplication.class, args);
}
}
public static ConfigurableApplicationContext run(Class<?> primarySource,
String... args) {
//空壳方法,继续跟
return run(new Class<?>[] { primarySource }, args);
}
public static ConfigurableApplicationContext run(Class<?>[] primarySources,
String[] args) {
//这里创建了SpringApplication对象,并调用了run方法
return new SpringApplication(primarySources).run(args);
}
SpringApplication 的构造方法
public SpringApplication(Class<?>... primarySources) {
//空壳方法,继续跟
this(null, primarySources);
}
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
//这里的resourceLoader为null
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
//判断web应用类型,有可能是servlet、reactive或者非web项目。这里主要是判断对应的类是否存在,自己看
this.webApplicationType = WebApplicationType.deduceFromClasspath();
//设置初始化器
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
//设置监听器
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
//获取main方法入口的类,这里是用异常的堆栈来获取main的method再反射获取类,自己看
this.mainApplicationClass = deduceMainApplicationClass();
}
讲讲 getSpringFactoriesInstances 方法。getSpringFactoriesInstances 主要是从 spring.factories 文件中获取对应的值,再反射生成对应的类。值得注意的是 这个方法会合并所有的 spring.factories 文件内容,看看 spring.factories 的内容格式
# Application Context Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
org.springframework.boot.context.ContextIdApplicationContextInitializer,\
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer
# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.ClearCachesApplicationListener,\
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
org.springframework.boot.context.FileEncodingApplicationListener,\
org.springframework.boot.context.config.AnsiOutputApplicationListener,\
org.springframework.boot.context.config.ConfigFileApplicationListener,\
org.springframework.boot.context.config.DelegatingApplicationListener,\
org.springframework.boot.context.logging.ClasspathLoggingApplicationListener,\
org.springframework.boot.context.logging.LoggingApplicationListener,\
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener
SpringApplication 的 run 方法
public ConfigurableApplicationContext run(String... args) {
//这个可以看做一个时间计数器,记录应用启动耗时
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
//配置一些界面的属性,如jwt之类的
configureHeadlessProperty();
//获取监听器
SpringApplicationRunListeners listeners = getRunListeners(args);
//发送开始事件
listeners.starting();
try {
//封装参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
//封装环境
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
//配置需要忽略的bean
configureIgnoreBeanInfo(environment);
//打印banner
Banner printedBanner = printBanner(environment);
//创建应用程序上下文对象
context = createApplicationContext();
//从spring.factories中获取SpringBootExceptionReporter对象,报告异常信息
exceptionReporters = getSpringFactoriesInstances(
SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
//预准备上下文
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);
//调用Runner,这里调用ApplicationRunner和CommandLineRunner接口的回调方法
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
//启动失败,打印异常信息
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
//发送运行中事件
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}
注意,SpringBoot是基于事件驱动的,事件监听器很重要。
getRunListeners 方法
private SpringApplicationRunListeners getRunListeners(String[] args) {
Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
//这里直接创建了一个 SpringApplicationRunListeners 对象并返回
//这里的getSpringFactoriesInstances方法从spring.factories中获取SpringApplicationRunListener的实现类EventPublishingRunListener
return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(
SpringApplicationRunListener.class, types, this, args));
}
SpringApplicationRunListeners
class SpringApplicationRunListeners {
private final Log log;
private final List<SpringApplicationRunListener> listeners;
SpringApplicationRunListeners(Log log,
Collection<? extends SpringApplicationRunListener> listeners) {
this.log = log;
//这里的lisenters就是从spring.factories中获取SpringApplicationRunListener的实现类EventPublishingRunListener
this.listeners = new ArrayList<>(listeners);
}
public void starting() {
for (SpringApplicationRunListener listener : this.listeners) {
listener.starting();
}
}
public void environmentPrepared(ConfigurableEnvironment environment) {
for (SpringApplicationRunListener listener : this.listeners) {
listener.environmentPrepared(environment);
}
}
public void contextPrepared(ConfigurableApplicationContext context) {
for (SpringApplicationRunListener listener : this.listeners) {
listener.contextPrepared(context);
}
}
public void contextLoaded(ConfigurableApplicationContext context) {
for (SpringApplicationRunListener listener : this.listeners) {
listener.contextLoaded(context);
}
}
public void started(ConfigurableApplicationContext context) {
for (SpringApplicationRunListener listener : this.listeners) {
listener.started(context);
}
}
public void running(ConfigurableApplicationContext context) {
for (SpringApplicationRunListener listener : this.listeners) {
listener.running(context);
}
}
public void failed(ConfigurableApplicationContext context, Throwable exception) {
for (SpringApplicationRunListener listener : this.listeners) {
callFailedListener(listener, context, exception);
}
}
private void callFailedListener(SpringApplicationRunListener listener,
ConfigurableApplicationContext context, Throwable exception) {
try {
listener.failed(context, exception);
}
catch (Throwable ex) {
if (exception == null) {
ReflectionUtils.rethrowRuntimeException(ex);
}
if (this.log.isDebugEnabled()) {
this.log.error("Error handling failed", ex);
}
else {
String message = ex.getMessage();
message = (message != null) ? message : "no error message";
this.log.warn("Error handling failed (" + message + ")");
}
}
}
}
从 SpringApplicationRunListeners 类中可以看出,所有的事件都是通过 listeners 即EventPublishingRunListener对象来发布的。
EventPublishingRunListener
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {
private final SpringApplication application;
private final String[] args;
private final SimpleApplicationEventMulticaster initialMulticaster;
public EventPublishingRunListener(SpringApplication application, String[] args) {
this.application = application;
this.args = args;
//构造方法中初始化了一个事件广播器
this.initialMulticaster = new SimpleApplicationEventMulticaster();
//事件广播器添加了所有的事件监听器,这里就是观察者模式的实现
for (ApplicationListener<?> listener : application.getListeners()) {
this.initialMulticaster.addApplicationListener(listener);
}
}
@Override
public int getOrder() {
return 0;
}
@Override
public void starting() {
this.initialMulticaster.multicastEvent(
new ApplicationStartingEvent(this.application, this.args));
}
@Override
public void environmentPrepared(ConfigurableEnvironment environment) {
this.initialMulticaster.multicastEvent(new ApplicationEnvironmentPreparedEvent(
this.application, this.args, environment));
}
@Override
public void contextPrepared(ConfigurableApplicationContext context) {
this.initialMulticaster.multicastEvent(new ApplicationContextInitializedEvent(
this.application, this.args, context));
}
@Override
public void contextLoaded(ConfigurableApplicationContext context) {
for (ApplicationListener<?> listener : this.application.getListeners()) {
if (listener instanceof ApplicationContextAware) {
((ApplicationContextAware) listener).setApplicationContext(context);
}
context.addApplicationListener(listener);
}
this.initialMulticaster.multicastEvent(
new ApplicationPreparedEvent(this.application, this.args, context));
}
@Override
public void started(ConfigurableApplicationContext context) {
context.publishEvent(
new ApplicationStartedEvent(this.application, this.args, context));
}
@Override
public void running(ConfigurableApplicationContext context) {
context.publishEvent(
new ApplicationReadyEvent(this.application, this.args, context));
}
@Override
public void failed(ConfigurableApplicationContext context, Throwable exception) {
ApplicationFailedEvent event = new ApplicationFailedEvent(this.application,
this.args, context, exception);
if (context != null && context.isActive()) {
// Listeners have been registered to the application context so we should
// use it at this point if we can
context.publishEvent(event);
}
else {
// An inactive context may not have a multicaster so we use our multicaster to
// call all of the context's listeners instead
if (context instanceof AbstractApplicationContext) {
for (ApplicationListener<?> listener : ((AbstractApplicationContext) context)
.getApplicationListeners()) {
this.initialMulticaster.addApplicationListener(listener);
}
}
this.initialMulticaster.setErrorHandler(new LoggingErrorHandler());
this.initialMulticaster.multicastEvent(event);
}
}
private static class LoggingErrorHandler implements ErrorHandler {
private static Log logger = LogFactory.getLog(EventPublishingRunListener.class);
@Override
public void handleError(Throwable throwable) {
logger.warn("Error calling ApplicationEventListener", throwable);
}
}
}
从EventPublishingRunListener中可以看出,所有的事件发布都是通过事件广播器来发布的,所有的事件监听器都注册到来事件广播器,这里用到了观察者模式。
在EventPublishingRunListener中封装了一些基础的事件类型
SimpleApplicationEventMulticaster 事件广播器
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
@Nullable
private Executor taskExecutor;
@Nullable
private ErrorHandler errorHandler;
/**
* Create a new SimpleApplicationEventMulticaster.
*/
public SimpleApplicationEventMulticaster() {
}
/**
* Create a new SimpleApplicationEventMulticaster for the given BeanFactory.
*/
public SimpleApplicationEventMulticaster(BeanFactory beanFactory) {
setBeanFactory(beanFactory);
}
/**
* Set a custom executor (typically a {@link org.springframework.core.task.TaskExecutor})
* to invoke each listener with.
* <p>Default is equivalent to {@link org.springframework.core.task.SyncTaskExecutor},
* executing all listeners synchronously in the calling thread.
* <p>Consider specifying an asynchronous task executor here to not block the
* caller until all listeners have been executed. However, note that asynchronous
* execution will not participate in the caller's thread context (class loader,
* transaction association) unless the TaskExecutor explicitly supports this.
* @see org.springframework.core.task.SyncTaskExecutor
* @see org.springframework.core.task.SimpleAsyncTaskExecutor
*/
public void setTaskExecutor(@Nullable Executor taskExecutor) {
this.taskExecutor = taskExecutor;
}
/**
* Return the current task executor for this multicaster.
*/
@Nullable
protected Executor getTaskExecutor() {
return this.taskExecutor;
}
/**
* Set the {@link ErrorHandler} to invoke in case an exception is thrown
* from a listener.
* <p>Default is none, with a listener exception stopping the current
* multicast and getting propagated to the publisher of the current event.
* If a {@linkplain #setTaskExecutor task executor} is specified, each
* individual listener exception will get propagated to the executor but
* won't necessarily stop execution of other listeners.
* <p>Consider setting an {@link ErrorHandler} implementation that catches
* and logs exceptions (a la
* {@link org.springframework.scheduling.support.TaskUtils#LOG_AND_SUPPRESS_ERROR_HANDLER})
* or an implementation that logs exceptions while nevertheless propagating them
* (e.g. {@link org.springframework.scheduling.support.TaskUtils#LOG_AND_PROPAGATE_ERROR_HANDLER}).
* @since 4.1
*/
public void setErrorHandler(@Nullable ErrorHandler errorHandler) {
this.errorHandler = errorHandler;
}
/**
* Return the current error handler for this multicaster.
* @since 4.1
*/
@Nullable
protected ErrorHandler getErrorHandler() {
return this.errorHandler;
}
@Override
public void multicastEvent(ApplicationEvent event) {
multicastEvent(event, resolveDefaultEventType(event));
}
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
//根据type和event类型获取所有对应的事件监听器
for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
Executor executor = getTaskExecutor();
//有线程池就异步执行,没有线程池就同步执行
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}
private ResolvableType resolveDefaultEventType(ApplicationEvent event) {
return ResolvableType.forInstance(event);
}
/**
* Invoke the given listener with the given event.
* @param listener the ApplicationListener to invoke
* @param event the current event to propagate
* @since 4.1
*/
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
ErrorHandler errorHandler = getErrorHandler();
if (errorHandler != null) {
try {
doInvokeListener(listener, event);
}
catch (Throwable err) {
errorHandler.handleError(err);
}
}
else {
doInvokeListener(listener, event);
}
}
@SuppressWarnings({"unchecked", "rawtypes"})
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
listener.onApplicationEvent(event);
}
catch (ClassCastException ex) {
String msg = ex.getMessage();
if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
// Possibly a lambda-defined listener which we could not resolve the generic event type for
// -> let's suppress the exception and just log a debug message.
Log logger = LogFactory.getLog(getClass());
if (logger.isDebugEnabled()) {
logger.debug("Non-matching event type for listener: " + listener, ex);
}
}
else {
throw ex;
}
}
}
private boolean matchesClassCastMessage(String classCastMessage, Class<?> eventClass) {
// On Java 8, the message starts with the class name: "java.lang.String cannot be cast..."
if (classCastMessage.startsWith(eventClass.getName())) {
return true;
}
// On Java 11, the message starts with "class ..." a.k.a. Class.toString()
if (classCastMessage.startsWith(eventClass.toString())) {
return true;
}
// On Java 9, the message used to contain the module name: "java.base/java.lang.String cannot be cast..."
int moduleSeparatorIndex = classCastMessage.indexOf('/');
if (moduleSeparatorIndex != -1 && classCastMessage.startsWith(eventClass.getName(), moduleSeparatorIndex + 1)) {
return true;
}
// Assuming an unrelated class cast failure...
return false;
}
}
createApplicationContext 方法
//根据web类型,通过反射生成对应的ConfigurableApplicationContext对象
protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
switch (this.webApplicationType) {
case SERVLET:
//public static final String DEFAULT_SERVLET_WEB_CONTEXT_CLASS = "org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext"
contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
break;
case REACTIVE:
//public static final String DEFAULT_REACTIVE_WEB_CONTEXT_CLASS = "org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext";
contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
break;
default:
//public static final String DEFAULT_CONTEXT_CLASS = "org.springframework.context.annotation.AnnotationConfigApplicationContext";
contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
}
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Unable create a default ApplicationContext, "
+ "please specify an ApplicationContextClass",
ex);
}
}
return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}
注意,这里的ApplicationContext对象是AnnotationConfigServletWebServerApplicationContext,表示是Servlet容器
prepareContext 方法
private void prepareContext(ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
//为当前上下文对象设置环境变量
context.setEnvironment(environment);
//aplicationContext的后置处理,添加beanNameGenerator、resourceLoader、addConversionService
postProcessApplicationContext(context);
//回调最开始设置的初始化器ApplicationContextInitializer
applyInitializers(context);
//发布上下文准备好事件
listeners.contextPrepared(context);
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// Add boot specific singleton beans
//获取beanFactory对象
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
//添加springApplicationArguments单例对象
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
//添加springBootBanner单例对象
if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
//设置运行覆盖,即后面的对象覆盖前面存在的对象
if (beanFactory instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory) beanFactory)
.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
// Load the sources
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
//加载资源application.yml application.properties
load(context, sources.toArray(new Object[0]));
//发布上下文加载完成事件
listeners.contextLoaded(context);
}