一给 发表于 2024-9-17 19:51:33

SpringBoot源码分析

Springboot源码分析

1、SpringApplication初始化

从run()方法进入,可以看到Springboot起首创建了SpringApplication,然后调用SpringApplication的run()方法。
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
    return (new SpringApplication(primarySources)).run(args);
}创建SpringApplication,起首要执行它的构造方法。
//SpringApplication.class
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
    this.sources = new LinkedHashSet();
    this.bannerMode = Mode.CONSOLE;
    this.logStartupInfo = true;
    this.addCommandLineProperties = true;
    this.addConversionService = true;
    this.headless = true;
    this.registerShutdownHook = true;
    this.additionalProfiles = new HashSet();
    this.isCustomEnvironment = false;
    this.lazyInitialization = false;
    this.resourceLoader = resourceLoader;
    Assert.notNull(primarySources, "PrimarySources must not be null");
    this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
    //webApplication类型一般是servlet
    this.webApplicationType = WebApplicationType.deduceFromClasspath();
   //设置初始化器,加载spring.factories文件中的ApplicationContextInitializer
    this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
    //设置监听器,加载spring.factories文件中的ApplicationListener
    this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
    //启动类的类型,我们的是com.example.demo.DemoApplication
    this.mainApplicationClass = this.deduceMainApplicationClass();
}1.1 & 1.2 设置初始化器和监听器

上面的setInitializers和setListeners去初始化spring.factories文件中对应的类,然后放入ArrayList中。比如这些:
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener

# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.autoconfigure.BackgroundPreinitializer1.2.1 getSpringFactoriesInstances

在getSpringFactoriesInstances()方法中,springboot起首去所有spring.factories找到对应的类,然后通过反射创建类的实例。
//SpringApplication.class
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
    return this.getSpringFactoriesInstances(type, new Class);
}

private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
    ClassLoader classLoader = this.getClassLoader();
    //获取spring.factories中对应类的类名,以ApplicationListenser为例,springboot会去文件中找到所有ApplicationListener对应的类,放入Set中。
    Set<String> names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
    //反射创建类的实例对象,放到List中返回
    List<T> instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
    AnnotationAwareOrderComparator.sort(instances);
    return instances;
}

private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, ClassLoader classLoader, Object[] args, Set<String> names) {
    List<T> instances = new ArrayList(names.size());
    Iterator var7 = names.iterator();

    while(var7.hasNext()) {
      String name = (String)var7.next();

      try {
            //获取类信息
            Class<?> instanceClass = ClassUtils.forName(name, classLoader);
            Assert.isAssignable(type, instanceClass);
            //获取构造器
            Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);
            //创建实例
            T instance = BeanUtils.instantiateClass(constructor, args);
            instances.add(instance);
      } catch (Throwable var12) {
            throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, var12);
      }
    }

    return instances;
}1.2.2 loadFactoryNames()

进入SpringFactoriesLoader.loadFactoryNames(type, classLoader)看一下,这里还是以ApplicationListener为例,这时的type是org.springframework.context.ApplicationListener,classLoader是AppClassLoader。
//SpringFactoriesLoader.class
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
    String factoryTypeName = factoryType.getName();
    return (List)loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
}

private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
    MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader);
    if (result != null) {
      return result;
    } else {
      try {
            Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
            MultiValueMap<String, String> result = new LinkedMultiValueMap();

            while(urls.hasMoreElements()) {
                URL url = (URL)urls.nextElement();
                UrlResource resource = new UrlResource(url);
                Properties properties = PropertiesLoaderUtils.loadProperties(resource);
                Iterator var6 = properties.entrySet().iterator();

                while(var6.hasNext()) {
                  Map.Entry<?, ?> entry = (Map.Entry)var6.next();
                  String factoryTypeName = ((String)entry.getKey()).trim();
                  String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
                  int var10 = var9.length;

                  for(int var11 = 0; var11 < var10; ++var11) {
                        String factoryImplementationName = var9;
                        result.add(factoryTypeName, factoryImplementationName.trim());
                  }
                }
            }

            cache.put(classLoader, result);
            return result;
      } catch (IOException var13) {
            throw new IllegalArgumentException("Unable to load factories from location ", var13);
      }
    }
}loadSpringFactories()方法会遍历所有的spring.factories文件,把所有的类的名字生存到map中,然后调用getOrDefault()方法就可以获取到所有的ApplicationListner对应的类名了。
https://img2023.cnblogs.com/blog/2754263/202409/2754263-20240912160505463-811496707.png
SpringApplication初始化完了,接下来该执行run()方法了
2、SpringApplication执行run()方法

//SpringApplication.class
public ConfigurableApplicationContext run(String... args) {
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    //这里是Spring的上下文
    ConfigurableApplicationContext context = null;
    Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
    this.configureHeadlessProperty();
    //获取运行监听器,获取到的是EventPublishingRunListener,这是springboot的启动监听器
    SpringApplicationRunListeners listeners = this.getRunListeners(args);
    //启动监听器
    listeners.starting();

    Collection exceptionReporters;
    try {
      ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
      //2.1 准备环境
      ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
      this.configureIgnoreBeanInfo(environment);
      //Banner打印类
      Banner printedBanner = this.printBanner(environment);
      //2.2 创建应用上下文
      context = this.createApplicationContext();
      exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
      //2.3 准备上下文
      this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
      //2.4 刷新上下文
      this.refreshContext(context);
      //刷新上下文后置处理
      this.afterRefresh(context, applicationArguments);
      stopWatch.stop();
      if (this.logStartupInfo) {
            (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
      }
                //发布上下文启动完成事件
      listeners.started(context);
      this.callRunners(context, applicationArguments);
    } catch (Throwable var10) {
      this.handleRunFailure(context, var10, exceptionReporters, listeners);
      throw new IllegalStateException(var10);
    }

    try {
      listeners.running(context);
      return context;
    } catch (Throwable var9) {
      this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
      throw new IllegalStateException(var9);
    }
}2.1 prepareEnvironment()准备环境

//SpringApplication.class
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) {
    //根据前面推断的webApplicationType创建对应的环境,servlet对应的是StandardServletEnvironment()
    ConfigurableEnvironment environment = this.getOrCreateEnvironment();
    //根据参数配置环境,包括命令行参数,启动类传入的参数
    this.configureEnvironment((ConfigurableEnvironment)environment, applicationArguments.getSourceArgs());
    ConfigurationPropertySources.attach((Environment)environment);
    //执行完这个,配置文件中的配置进行就被加载到环境中了
    listeners.environmentPrepared((ConfigurableEnvironment)environment);
    //环境和SpringApplication绑定起来
    this.bindToSpringApplication((ConfigurableEnvironment)environment);
    if (!this.isCustomEnvironment) {
      environment = (new EnvironmentConverter(this.getClassLoader())).convertEnvironmentIfNecessary((ConfigurableEnvironment)environment, this.deduceEnvironmentClass());
    }

    ConfigurationPropertySources.attach((Environment)environment);
    return (ConfigurableEnvironment)environment;
}2.1.1 根据参数配置环境configureEnvironment()

//SpringApplication.class
protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
    if (this.addConversionService) {
      ConversionService conversionService = ApplicationConversionService.getSharedInstance();
      environment.setConversionService((ConfigurableConversionService)conversionService);
    }
        //配置命令行中的参数
    this.configurePropertySources(environment, args);
    //激活相应的配置文件,例如application.propertires或者application-dev.properties等
    this.configureProfiles(environment, args);
}如果我启动的dev环境,执行完上面的代码后环境中是这样的
https://img2023.cnblogs.com/blog/2754263/202409/2754263-20240912160505065-376220975.png
2.1.2 listeners.environmentPrepared()

执行完这句代码后,配置文件中的信息就被加载到环境中了,如下图。具体怎么做到的还没看懂
https://img2023.cnblogs.com/blog/2754263/202409/2754263-20240912160504680-843829619.png
2.2 创建应用上下文createApplicationContext()

//SpringApplication.class
protected ConfigurableApplicationContext createApplicationContext() {
    Class<?> contextClass = this.applicationContextClass;
    if (contextClass == null) {
      try {
            switch (this.webApplicationType) {
                case SERVLET:
                  contextClass = Class.forName("org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext");
                  break;
                case REACTIVE:
                  contextClass = Class.forName("org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext");
                  break;
                default:
                  contextClass = Class.forName("org.springframework.context.annotation.AnnotationConfigApplicationContext");
            }
      } catch (ClassNotFoundException var3) {
            throw new IllegalStateException("Unable create a default ApplicationContext, please specify an ApplicationContextClass", var3);
      }
    }

    return (ConfigurableApplicationContext)BeanUtils.instantiateClass(contextClass);
}这个函数也是根据前面的webApplicationType创建应用上下文,servlet对应的是AnnotationConfigServletWebServerApplicationContext,当初始化完这个类时,其实也会创建一个IOC容器beanFactory,如下图所示。这是因为AnnotationConfigServletWebServerApplicationContext会继承GenericApplicationContext,当执行完这个类的构造函数,会创建一个DefaultListableBeanFactory()的beanFactory,这个就是IOC容器。
https://img2023.cnblogs.com/blog/2754263/202409/2754263-20240912160504223-854337640.png
2.3 准备上下文prepareContext()

//SpringApplication.class
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
    //设置上下文环境
    context.setEnvironment(environment);
    this.postProcessApplicationContext(context);
    //初始化所有的ApplicationContextInitializer
    this.applyInitializers(context);
    //发布上下文准备完成事件
    listeners.contextPrepared(context);
    if (this.logStartupInfo) {
      this.logStartupInfo(context.getParent() == null);
      this.logStartupProfileInfo(context);
    }
    //获取IOC容器beanFactory
    ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
    //将springApplicationArguments和springBootBanner注册成单例
    beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
    if (printedBanner != null) {
      beanFactory.registerSingleton("springBootBanner", printedBanner);
    }

    if (beanFactory instanceof DefaultListableBeanFactory) {
      ((DefaultListableBeanFactory)beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
    }

    if (this.lazyInitialization) {
      context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
    }
        //2.3.1 获取资源,其中primarySources就是我们定义的启动类DemoApplication
    Set<Object> sources = this.getAllSources();
    Assert.notEmpty(sources, "Sources must not be empty");
    //2.3.2 加载启动类,注入IOC容器
    this.load(context, sources.toArray(new Object));
    //发布完成加载事件
    listeners.contextLoaded(context);
}2.3.1 & 2.3.2 获取启动类,注入IOC容器

当执行完getAllSources(),可以获取到启动类DemoApplication
https://img2023.cnblogs.com/blog/2754263/202409/2754263-20240912160503857-611438687.png
重点看load()方法,进入load()。
//SpringApplication.class
protected void load(ApplicationContext context, Object[] sources) {
    if (logger.isDebugEnabled()) {
      logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
    }
        //创建BeanDefinitionLoader
    BeanDefinitionLoader loader = this.createBeanDefinitionLoader(this.getBeanDefinitionRegistry(context), sources);
    if (this.beanNameGenerator != null) {
      loader.setBeanNameGenerator(this.beanNameGenerator);
    }

    if (this.resourceLoader != null) {
      loader.setResourceLoader(this.resourceLoader);
    }

    if (this.environment != null) {
      loader.setEnvironment(this.environment);
    }
        //加载启动类
    loader.load();
}其中getBeanDefinitionRegistry(context)方法会将之前的上下文context强转成BeanDefinitionRegistry,他们之间的继承关系很复杂,可以转换成不同的类完成不同的方法。createBeanDefinitionLoader()方法创建了一个BeanDefinitionLoader(),点进去看看。
//BeanDefinitionLoader.class
BeanDefinitionLoader(BeanDefinitionRegistry registry, Object... sources) {
    Assert.notNull(registry, "Registry must not be null");
    Assert.notEmpty(sources, "Sources must not be empty");
    this.sources = sources;
    //注解形式的Bean阅读器
    this.annotatedReader = new AnnotatedBeanDefinitionReader(registry);
    //xml形式的Bean阅读器
    this.xmlReader = new XmlBeanDefinitionReader(registry);
    if (this.isGroovyPresent()) {
      this.groovyReader = new GroovyBeanDefinitionReader(registry);
    }
        //类路径扫描器
    this.scanner = new ClassPathBeanDefinitionScanner(registry);
    this.scanner.addExcludeFilter(new ClassExcludeFilter(sources));
}一直跟进load()。
//BeanDefinitionLoader.class
private int load(Class<?> source) {
    if (this.isGroovyPresent() && GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
      GroovyBeanDefinitionSource loader = (GroovyBeanDefinitionSource)BeanUtils.instantiateClass(source, GroovyBeanDefinitionSource.class);
      this.load(loader);
    }
        //启动类会走进这里
    if (this.isEligible(source)) {
      //将启动类注册进beanDefinitionMap
      this.annotatedReader.register(new Class[]{source});
      return 1;
    } else {
      return 0;
    }
}进入register()方法。
//AnnotatedBeanDefinitionReader.classpublic void register(Class... componentClasses) {    Class[] var2 = componentClasses;    int var3 = componentClasses.length;    for(int var4 = 0; var4 < var3; ++var4) {      Class componentClass = var2;      this.registerBean(componentClass);    }}public void registerBean(Class beanClass) {    this.doRegisterBean(beanClass, (String)null, (Class[])null, (Supplier)null, (BeanDefinitionCustomizer[])null);}privatevoid doRegisterBean(Class beanClass, @Nullable String name, @Nullable Class
页: [1]
查看完整版本: SpringBoot源码分析