这样深度Spring Boot的源码解析,看完帮你立即提升一个台阶

1 实例化SpringApplication

SpringApplication.run(BootifulApplication.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); //new SpringApplication}
public SpringApplication(Class<?>... primarySources) {this(, primarySources);}
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {//设置资源加载器为this.resourceLoader = resourceLoader;//断言加载资源类不能为Assert.not(primarySources, "PrimarySources must not be ");//将primarySources数组转换为List,最后放到LinkedHashSet集合中this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));//【1.1 推断当前应用类型是否为WEB】this.webApplicationType = WebApplicationType.deduceFromClasspath;//【1.2 设置应用上下文初始化器】setInitializers((Collection) getSpringFactoriesInstances( ApplicationContextInitializer.class));//【1.3 设置监听器】setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));//【1.4 推断应用的入口类】this.mainApplicationClass = deduceMainApplicationClass;}

 

1.1 推断当前应用类型是否为WEB

根据classpath下的内容推断出应用的类型

this.webApplicationType = WebApplicationType.deduceFromClasspath;

static WebApplicationType deduceFromClasspath { if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, ) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, ) && !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, )) { return WebApplicationType.REACTIVE; } for (String className : SERVLET_INDICATOR_CLASSES) { if (!ClassUtils.isPresent(className, )) { return WebApplicationType.NONE; } } return WebApplicationType.SERVLET;}

 

1.2 设置应用上下文初始化器

setInitializers((Collection)getSpringFactoriesInstances(ApplicationContextInitializer.class));

  • ApplicationContextInitializer

public interface ApplicationContextInitializer<C extends ConfigurableApplicationContext> { /** * Initialize the given application context. * @param applicationContext the application to configure */ void initialize(C applicationContext);}
  • getSpringFactoriesInstances(ApplicationContextInitializer.class)

private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) { return getSpringFactoriesInstances(type, new Class<?>[] {});}
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) { //获取当前上下文类加载器 ClassLoader classLoader = getClassLoader; // Use names and ensure unique to protect against duplicates //获取ApplicationContextInitializer实例名称并且去重 Set<String> names = new LinkedHashSet<>( //进入loadFactoryNames方法并且找到loadSpringFactories---spring.factories SpringFactoriesLoader.loadFactoryNames(type, classLoader)); //创建初始化器实例列表 List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names); //排序 AnnotationAwareOrderComparator.sort(instances); return instances;}
  • setInitializers(...)

初始化一个ApplicationContextInitializer

public void setInitializers( Collection<? extends ApplicationContextInitializer<?>> initializers) { this.initializers = new ArrayList<>; this.initializers.addAll(initializers);}

 

1.3 设置监听器

setListeners((Collection)getSpringFactoriesInstances(ApplicationListener.class));

  • ApplicationListener

public interface ApplicationListener<E extends ApplicationEvent> extends EventListener { /** * Handle an application event. * @param event the event to respond to */ void onApplicationEvent(E event);}
  • getSpringFactoriesInstances(ApplicationListener.class)

private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) { return getSpringFactoriesInstances(type, new Class<?>[] {});}
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) { //获取当前上下文类加载器 ClassLoader classLoader = getClassLoader; // Use names and ensure unique to protect against duplicates //获取ApplicationContextInitializer实例名称并且去重 Set<String> names = new LinkedHashSet<>( //进入loadFactoryNames方法并且找到loadSpringFactories---spring.factories SpringFactoriesLoader.loadFactoryNames(type, classLoader)); List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names); //创建初始化器实例列表 AnnotationAwareOrderComparator.sort(instances); //排序 return instances;}
  • setListeners(...)

初始化一个ApplicationListener

public void setListeners(Collection<? extends ApplicationListener<?>> listeners) { this.listeners = new ArrayList<>; this.listeners.addAll(listeners);}

 

1.4 推断应用的入口类

this.mainApplicationClass = deduceMainApplicationClass;
private Class<?> deduceMainApplicationClass { try { //构造一个运行时异常,遍历异常栈中的方法名,获取方法名为main的栈帧,得到入口类的名字再返回该类 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 ;}

 

2 调用run方法

/** * Run the Spring application, creating and refreshing a new * {@link ApplicationContext}. * @param args the application arguments (usually passed from a Java main method) * @return a running {@link ApplicationContext}*/public ConfigurableApplicationContext run(String... args) {//创建计时类StopWatch stopWatch = new StopWatch;stopWatch.start;//初始化应用上下文和异常报告集合ConfigurableApplicationContext context = ;Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>;//设置headless属性configureHeadlessProperty;//【2.1 创建运行监听器】SpringApplicationRunListeners listeners = getRunListeners(args);//发布应用启动事件listeners.starting;try { //初始化默认应用参数类 ApplicationArguments applicationArguments = new DefaultApplicationArguments( args); //【2.2 根据监听器和应用参数类准备Spring环境】 ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); configureIgnoreBeanInfo(environment); //创建Banner打印类 Banner printedBanner = printBanner(environment); //【2.3 创建应用上下文】 context = createApplicationContext; //准备异常报告 exceptionReporters = getSpringFactoriesInstances( SpringBootExceptionReporter.class, new Class[] { ConfigurableApplicationContext.class }, context); //【2.4 准备应用上下文】 prepareContext(context, environment, listeners, applicationArguments, printedBanner); //【2.5 刷新应用上下文】 refreshContext(context); //应用上下文后置处理刷新 afterRefresh(context, applicationArguments); //停止计时类 stopWatch.stop; //输出日志记录执行主类名、时间信息 if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass) .logStarted(getApplicationLog, stopWatch); } //发布应用上下文启动完成事件 listeners.started(context); //【2.6 执行Runner运行器】 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, ); throw new IllegalStateException(ex);}//返回应用上下文return context;}

 

2.1 创建运行监听器

SpringApplicationRunListeners listeners = getRunListeners(args);

private SpringApplicationRunListeners getRunListeners(String[] args) { Class<?> types = new Class<?> { SpringApplication.class, String.class }; return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances( SpringApplicationRunListener.class, types, this, args));}
  • SpringApplicationRunListener

org.springframework.boot:spring-boot/META-INF/spring.factories

  • getSpringFactoriesInstances(...)

private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) { ClassLoader classLoader = getClassLoader; // Use names and ensure unique to protect against duplicates Set<String> names = new LinkedHashSet<>( SpringFactoriesLoader.loadFactoryNames(type, classLoader)); List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names); AnnotationAwareOrderComparator.sort(instances); return instances;}
  • new SpringApplicationRunListeners(...)

SpringApplicationRunListeners(Log log, Collection<? extends SpringApplicationRunListener> listeners) { this.log = log; this.listeners = new ArrayList<>(listeners);}

 

2.2 根据监听器和应用参数类准备Spring环境

ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);

private ConfigurableEnvironment prepareEnvironment( SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) { // Create and configure the environment //获取应用环境(3种情况) ConfigurableEnvironment environment = getOrCreateEnvironment; //配置应用环境 configureEnvironment(environment, applicationArguments.getSourceArgs); listeners.environmentPrepared(environment); bindToSpringApplication(environment); if (!this.isCustomEnvironment) { environment = new EnvironmentConverter(getClassLoader) .convertEnvironmentIfNecessary(environment, deduceEnvironmentClass); } ConfigurationPropertySources.attach(environment); return environment;}

 

2.3 创建应用上下文

context = createApplicationContext;

protected ConfigurableApplicationContext createApplicationContext { Class<?> contextClass = this.applicationContextClass; if (contextClass == ) { 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: 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);}

 

2.4 准备应用上下文

prepareContext(context, environment, listeners, applicationArguments, printedBanner);

private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) { //绑定环境到上下文 context.setEnvironment(environment); //配置上下文的bean生成器和资源加载器 postProcessApplicationContext(context); //为上下文采用所有初始化器 applyInitializers(context); //触发监听器的contextPrepared事件 listeners.contextPrepared(context); //记录启动日志 if (this.logStartupInfo) { logStartupInfo(context.getParent == ); logStartupProfileInfo(context); } // Add boot specific singleton beans //注册两个特殊的单例Bean ConfigurableListableBeanFactory beanFactory = context.getBeanFactory; beanFactory.registerSingleton("springApplicationArguments", applicationArguments); if (printedBanner != ) { 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"); load(context, sources.toArray(new Object[0])); //触发监听器的contextLoaded事件 listeners.contextLoaded(context);}

 

2.5 刷新应用上下文

refreshContext(context);

private void refreshContext(ConfigurableApplicationContext context) { refresh(context); //--->进入该方法 if (this.registerShutdownHook) { try { context.registerShutdownHook; } catch (AccessControlException ex) { // Not allowed in some environments. } }}
protected void refresh(ApplicationContext applicationContext) { Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext); ((AbstractApplicationContext) applicationContext).refresh; //--->进入该方法}
public void refresh throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. //context:启动日期|设置context当前状态|初始化环境|验证必须 prepareRefresh;
 // Tell the subclass to refresh the internal bean factory. //刷新内部bean工厂,即创建一个bean工厂(对BeanDefinition的定义、解析、处理和注册) ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory;
 // Prepare the bean factory for use in this context. //上面创建好了之后,还需要配置一些东西才能使用 prepareBeanFactory(beanFactory);
 try { // Allows post-processing of the bean factory in context subclasses. //注册WEB特性的scope(如request,session等) postProcessBeanFactory(beanFactory);
 // Invoke factory processors registered as beans in the context. //调用所有的bean工厂处理器对bean进行一些处理 invokeBeanFactoryPostProcessors(beanFactory);
 // Register bean processors that intercept bean creation. //注册用来拦截bean registerBeanPostProcessors(beanFactory);
 // Initialize message source for this context. //主要用于国际化 initMessageSource;
 // Initialize event multicaster for this context. //为context初始化一个事件广播器 initApplicationEventMulticaster;
 // Initialize other special beans in specific context subclasses. /* 在AbstractApplicationContext的子类中初始化其他特殊的bean。 其实就是初始化ThemeSource接口的实例。这个方法需要在所有单例bean初始化之前调用。 */ onRefresh;
 // Check for listener beans and register them. //注册应用监听器 registerListeners;
 // Instantiate all remaining (non-lazy-init) singletons. //完成对bean工厂初始化工作 finishBeanFactoryInitialization(beanFactory);
 // Last step: publish corresponding event. //调用LifecycleProcessor的onRefresh方法并且发布事件 finishRefresh; }
 catch (BeansException ex) { if (logger.isWarnEnabled) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); }
 // Destroy already created singletons to avoid dangling resources. destroyBeans;
 // Reset 'active' flag. cancelRefresh(ex);
 // Propagate exception to caller. throw ex; }
 finally { // Reset common introspection caches in Spring's core, since we // might not ever need metadata for singleton beans anymore... resetCommonCaches; } }}

 

2.6 执行Runner运行器

callRunners(context, applicationArguments);

执行所有ApplicationRunner和CommandLineRunner两种运行器

private void callRunners(ApplicationContext context, ApplicationArguments args) { List<Object> runners = new ArrayList<>; runners.addAll(context.getBeansOfType(ApplicationRunner.class).values); runners.addAll(context.getBeansOfType(CommandLineRunner.class).values); AnnotationAwareOrderComparator.sort(runners); for (Object runner : new LinkedHashSet<>(runners)) { if (runner instanceof ApplicationRunner) { callRunner((ApplicationRunner) runner, args); } if (runner instanceof CommandLineRunner) { callRunner((CommandLineRunner) runner, args); } }}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值