A list,

  • Springboot source code parsing is a big project, line by line to study the code, can be boring, and not easy to stick to.
  • We do not pursue big and complete, but try to study a small knowledge point every time, and eventually together, this is our Springboot source tube leopard series.

Second, the framework

We first springboot source framework to understand clearly.

1. Create a SpringBoot project

import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class MyprojectApplication { public static void main(String[] args) { SpringApplication.run(MyprojectApplication.class, args); }}Copy the code

2. Analyze the source code

Compared to a Spring project or a SpringMVC project, the springBoot entry is very easy to find, just in the Run method in main, so we go to the Run method

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); }Copy the code

Using the static method of SpringApplication, we create a new SpringApplication class and call its Run method. We first look at the constructor of SpringApplication and then look at the run method

public SpringApplication(Class<? >... primarySources) { this(null, primarySources); } @SuppressWarnings({ "unchecked", "rawtypes" }) public SpringApplication(ResourceLoader resourceLoader, Class<? >... primarySources) { this.resourceLoader = resourceLoader; Assert.notNull(primarySources, "PrimarySources must not be null"); this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources)); this.webApplicationType = WebApplicationType.deduceFromClasspath(); setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)); setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); this.mainApplicationClass = deduceMainApplicationClass(); }Copy the code

The constructor does these things:

  • Determine the Web type: webApplicationType
  • Loading ApplicationContextInitializer
  • Load the ApplicationListener
  • Determine the implementation class of applicationContext

Let’s skip the implementation details and look at the run method

public ConfigurableApplicationContext run(String... args) {
  StopWatch stopWatch = new StopWatch();
  stopWatch.start();
  ConfigurableApplicationContext context = null;
  Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
  configureHeadlessProperty();
  SpringApplicationRunListeners listeners = getRunListeners(args);
  listeners.starting();
  try {
   ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
    ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
    configureIgnoreBeanInfo(environment);
    Banner printedBanner = printBanner(environment);
    context = createApplicationContext();
    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);
    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;
}
Copy the code

The run method does several things:

  • Stopwatch Records the springboot startup time
  • Different phases trigger Spring’s Listen events
  • Create the ApplicationContext implementation class
  • Start Spring: refreshContext(context)
  • Start finish loading runner

The most important is the refreshContext method, which is a continuation of the Fresh method of SpringFrame

private void refreshContext(ConfigurableApplicationContext context) {
  refresh((ApplicationContext) context);
  if (this.registerShutdownHook) {
    try {
        context.registerShutdownHook();
    }
    catch (AccessControlException ex) {
        // Not allowed in some environments.
    }
  }
}
Copy the code

AbstractApplicationContext class methods

public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. prepareRefresh(); // Tell the subclass to refresh the internal bean factory. 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. postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. registerBeanPostProcessors(beanFactory); // Initialize message source for this context. initMessageSource(); // Initialize event multicaster for this context. initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. onRefresh(); // Check for listener beans and register them. registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. 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(); }}}Copy the code

Don’t go into depth first, just look at it, understand the overall framework, so far the source code of the Springboot project is the main framework.

  • The core capability remains Spring’s Refresh method
  • More functionality is provided by encapsulation with SpringApplication.

That’s it for this installment, and from next installment, we’ll take the problem and look for implementations in the source code.

Welcome to pay attention to the public number: Fengji, more technical learning to share.