Spring源码简析(一)
Application启动
使用Spring-boot我们可以非常简单的就能搭建一个spring应用,开发人员可以直接通过Main方法启动的SpringApplication来启动Spring-boot
@SpringBootApplication
@EnableAutoConfiguration
public class DemoApplication extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(DemoApplication .class);
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication .class, args);
}
}
声明这样一个类,就是一个spring-boot的应用了,直接运行main方法就可以启动spring-boot。
SpringApplication提供了一个静态方法让用户启动框架,
public static ConfigurableApplicationContext run(Object source, String... args) {
return run(new Object[] { source }, args);
}
注意这里的source参数,我们传入的是我们自定义的类,这个参数的作用就是来帮助spring-boot确定要从哪里来加载bean,这个方法是动长参数,开发人员可以传入多个参数,这个在后续的代码解读中会继续说明。
public static ConfigurableApplicationContext run(Object[] sources, String[] args) {
return new SpringApplication(sources).run(args);
}
在创建了SpringApplication之后就开始运行应用,其中最重要的部分就是doRun方法
private ConfigurableApplicationContext doRun(SpringApplicationRunListeners listeners,
String... args) {
ConfigurableApplicationContext context;
// Create and configure the environment
ConfigurableEnvironment environment = getOrCreateEnvironment();
configureEnvironment(environment, args);
listeners.environmentPrepared(environment);
if (isWebEnvironment(environment) && !this.webEnvironment) {
environment = convertToStandardEnvironment(environment);
}
//打印banner,也就是平时启动时候打印的spring的标识
if (this.bannerMode != Banner.Mode.OFF) {
printBanner(environment);
}
// Create, load, refresh and run the ApplicationContext
//创建context,这个也是全局的bean容器
context = createApplicationContext();
//设置运行环境
context.setEnvironment(environment);
//预处理context,根据当前的环境配置beanNameGenerator和资源加载器
postProcessApplicationContext(context);
//加载各个包里/META_INF/spring.factory配置文件,每个包可以根据自己的特性在文件中配置SrpingContextInitializer接口,用来配置contex的一些属性
applyInitializers(context);
//
listeners.contextPrepared(context);
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//向容器中注册一个singleton的bean
context.getBeanFactory().registerSingleton("springApplicationArguments",
applicationArguments);
// 获取资源,这个就是启动Application的时候我们传入的
Set<Object> sources = getSources();
// 开始加载资源到容器
load(context, sources.toArray(new Object[sources.size()]));
listeners.contextLoaded(context);
// Refresh the context
refresh(context);
if (this.registerShutdownHook) {
try {
context.registerShutdownHook();
}
catch (AccessControlException ex) {
// Not allowed in some environments.
}
}
afterRefresh(context, applicationArguments);
listeners.finished(context, null);
return context;
}
这里的入参是一个SpringApplicationRunListeners 类,内部包含了多个SpringBootApplicationRunListener实例,这些类的实例是通过类似spi的方式获取并实例化的,用户可以在自己的工程META_INF/spring.factories中配置,具体方式可以参考spring-boot其他包中的配置方式。这个类主要是用来监听SpringApplication的生命周期用,包括启动,准备环境,创建context,load,finish等等。
经历了准备环境,创建context,load,refresh操作之后,我们的SpringApplication就启动完成了。