@SpringBootApplication
public class SpringBootDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootDemoApplication.class, args);
}
}
SpringApplication类的静态run方法,primarySource 这个类很关键,后面进行BFPP进行操作的时候,需要对这个类型上面的注解进行解析,这就是为啥springBoot正常情况下只能扫描启动类当前的包和子包的类进行IOC管理。
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);
}
SpringApplication的核心构造方法
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
// springboot项目的启动类,一切资源的基础
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
// webApplicationType的类型,根据类加载器是否存在相应的类来判断类型,来决定web容器的类型;NONE,SERVLET,REACTIVE
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 从MATE-INF/spring.factories 中查找是否有BootstrapRegistryInitializer类型的类,进行初始化
this.bootstrapRegistryInitializers = new ArrayList<>(
getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
// 从spring.factories中加载 ApplicationContextInitializer 类型的类
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 加载了 ApplicationListener
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
// 以上3个都是可以进行扩展的地方
// 获取启动main方法的类
this.mainApplicationClass = deduceMainApplicationClass();
}
SpringApplication的实例方法--run
public ConfigurableApplicationContext run(String... args) {
long startTime = System.nanoTime();
// 创建DefaultBootstrapContext 类,并使用构造函数中注册的BootstrapRegistryInitializer 实例对bootstrapContext 进行初始化操作,可以进行一些逻辑的操作
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
// java.awt.headless 参数设置
configureHeadlessProperty();
// 从MATE-INF/spring.factories文件中获取 SpringApplicationRunListener 类型的实例进行,包装在 listeners 中
// 默认listeners中只有一个 EventPublishingRunListener
SpringApplicationRunListeners listeners = getRunListeners(args);
// 对监听中中 SpringApplicationRunListener变量进行starting方法,默认实现使用多播器发布一个 ApplicationStartingEvent 的事件。
// 这里使用业务自定义的监听器监听没有效果,因为这个spring容器还没有初始化,对于的Bean还没有创建
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
// 参数包装
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// environment环境构建
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
// 配置 spring.beaninfo.ignore
configureIgnoreBeanInfo(environment);
// 打印 banner,启动命令输出
Banner printedBanner = printBanner(environment);
// 创建context,注册了内置的BFPP和BPP
context = createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
// context预处理,把环境准备好,把启动类的类型注册到 BeanFactory中
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
// 调用refresh方法进行 spring容器操作,tomcat容器也是在里面进行创建的
refreshContext(context);
// 扩展方法
afterRefresh(context, applicationArguments);
Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
}
// 发布启动成功事件,可以进行业务监听
listeners.started(context, timeTakenToStartup);
// 调用 Runner接口实现的类型
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
// 发布ready事件
listeners.ready(context, timeTakenToReady);
}
catch (Throwable ex) {
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
return context;
}
SpringApplication中的 createBootstrapContext方法
private DefaultBootstrapContext createBootstrapContext() {
DefaultBootstrapContext bootstrapContext = new DefaultBootstrapContext();
this.bootstrapRegistryInitializers.forEach((initializer) -> initializer.initialize(bootstrapContext));
return bootstrapContext;
}
SpringApplication中的 prepareEnvironment方法
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
// Create and configure the environment
// 创建或者获取一个enviroment对象,需要判断不同web容器类型来创建不同类型的对象
ConfigurableEnvironment environment = getOrCreateEnvironment();
// 环境配置
configureEnvironment(environment, applicationArguments.getSourceArgs());
// 判断是否有 configurationProperties key的source,如果没有就添加一个
ConfigurationPropertySources.attach(environment);
// 发布环境初始化时间
listeners.environmentPrepared(bootstrapContext, environment);
// 默认资源移动到最后 defaultProperties
DefaultPropertiesPropertySource.moveToEnd(environment);
Assert.state(!environment.containsProperty("spring.main.environment-prefix"),
"Environment prefix cannot be set via properties.");
// 把environment 绑定到 SpringApplication上
bindToSpringApplication(environment);
if (!this.isCustomEnvironment) {
environment = convertEnvironment(environment);
}
ConfigurationPropertySources.attach(environment);
return environment;
}
private ConfigurableEnvironment getOrCreateEnvironment() {
if (this.environment != null) {
return this.environment;
}
switch (this.webApplicationType) {
case SERVLET:
return new ApplicationServletEnvironment();
case REACTIVE:
return new ApplicationReactiveWebEnvironment();
default:
return new ApplicationEnvironment();
}
}
protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
if (this.addConversionService) {
environment.setConversionService(new ApplicationConversionService());
}
configurePropertySources(environment, args);
configureProfiles(environment, args);
}
根据不同给的类型创建不同的上下问题对象,这里研究 SERVLET 容器
ApplicationContextFactory DEFAULT = (webApplicationType) -> {
try {
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);
}
};
public AnnotationConfigServletWebServerApplicationContext() {
// 里面进行了 environment的创建,和注册了一些内部类internalConfigurationAnnotationProcessor,用于在BFPP,和BPP场景下使用
// AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry); 核心代码
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
// 覆盖环境变量
context.setEnvironment(environment);
// 配置一些context的属性
postProcessApplicationContext(context);
// 调用 ApplicationContextInitializer 的initialize继续进行初始化
applyInitializers(context);
// 发布事件
listeners.contextPrepared(context);
// 发送关闭 bootstrapContext的事件
bootstrapContext.close(context);
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// Add boot specific singleton beans
// 添加一个特殊的Bean
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
// 设置是否允许循环引用
if (beanFactory instanceof AbstractAutowireCapableBeanFactory) {
((AbstractAutowireCapableBeanFactory) beanFactory).setAllowCircularReferences(this.allowCircularReferences);
if (beanFactory instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory) beanFactory)
.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
}
if (this.lazyInitialization) {
context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
}
// Load the sources
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");、
// 它启动类传进来的类,注册到BeanFactory中
load(context, sources.toArray(new Object[0]));
// 发布事件
listeners.contextLoaded(context);
}