boot spring 解析csv_springboot源码架构解析springApplication

论坛 期权论坛 编程之家     
选择匿名的用户   2021-5-31 21:38   59   0

说在前面

前期回顾

sharding-jdbc源码解析 更新完毕

spring源码解析 更新完毕

spring-mvc源码解析 更新完毕

spring-tx源码解析 更新完毕

spring-boot源码解析 更新完毕

rocketmq源码解析 更新完毕

dubbbo源码解析 更新完毕

netty源码解析 更新完毕

spring源码架构更新完毕

spring-mvc源码架构更新完毕

springboot源码架构更新中

github https://github.com/tianheframe

sharding-jdbc源码解析 更新完毕

rocketmq源码解析 更新完毕

seata 源码解析 更新完毕

dubbo 源码解析 更新完毕

netty 源码解析 更新完毕

源码解析

e724bc681037e2a2caf7ed5c9235ac7e.png

org.springframework.boot.Banner banner接口类

void printBanner(Environment environment, Class> sourceClass, PrintStream out);

打印banner

enum Mode {    /**     * Disable printing of the banner.     */    OFF,    /**     * Print the banner to System.out.     */    CONSOLE,    /**     * Print the banner to the log file.     */    LOG  }

打印banner的三种方式,off禁止,console控制台,log 文件

org.springframework.boot.ResourceBanner 基于txt文件的banner打印

org.springframework.boot.SpringBootBanner 打印spring的banner

org.springframework.boot.ImageBanner 打印image的banner

org.springframework.boot.ApplicationArguments 提供对用于运行spring应用程序的参数的访问。

String[] getSourceArgs();

返回传递给应用程序的原始未处理参数。

Set<String> getOptionNames();

返回所有选项参数的名称。例如,如果参数是“——foo=bar——debug”,那么将返回值["foo", "debug"]。

boolean containsOption(String name);

返回从参数中解析的选项参数集是否包含具有给定名称的选项。

List<String> getOptionValues(String name);

返回与具有给定名称的arguments选项关联的值集合。如果该选项存在且没有参数(例如:"——foo"),则返回一个空集合([]),如果该选项存在并且只有一个值(例如。"——foo=bar"),返回一个只有一个元素的集合(["bar"]),如果该选项存在并具有多个值(例如,返回一个集合,其中每个值都有对应的元素(["bar", "baz"]),如果不存在该选项,则返回null

org.springframework.boot.DefaultApplicationArguments ApplicationArguments的默认实现

org.springframework.boot.context.properties.ConfigurationBeanFactoryMetaData 在bean工厂初始化期间记忆@Bean定义元数据的实用程序类。

实现了org.springframework.beans.factory.config.BeanFactoryPostProcessor接口

private ConfigurableListableBeanFactory beanFactory;

beanFactory

@Override  public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)      throws BeansException {    this.beanFactory = beanFactory;//    加载BeanFactory的BeanDefinition元数据    for (String name : beanFactory.getBeanDefinitionNames()) {      BeanDefinition definition = beanFactory.getBeanDefinition(name);      String method = definition.getFactoryMethodName();      String bean = definition.getFactoryBeanName();      if (method != null && bean != null) {        this.beans.put(name, new MetaData(bean, method));      }    }  }

重写了org.springframework.beans.factory.config.BeanFactoryPostProcessor#postProcessBeanFactory方法。

org.springframework.boot.SpringApplicationBannerPrinter 用SpringApplication打印 application bananer

org.springframework.boot.bind.YamlConfigurationFactory 通过将某些YAML绑定到指定类型的对象,然后选择在其上运行验证器来验证某些YAML。

private Validator validator;

validator

@Override  @SuppressWarnings("unchecked")  public void afterPropertiesSet() throws Exception {    if (this.yaml == null) {      Assert.state(this.resource != null, "Resource should not be null");      this.yaml = StreamUtils.copyToString(this.resource.getInputStream(),          Charset.defaultCharset());    }    Assert.state(this.yaml != null, "Yaml document should not be null: "        + "either set it directly or set the resource to load it from");    try {      if (logger.isTraceEnabled()) {        logger.trace(String.format("Yaml document is %n%s", this.yaml));      }      Constructor constructor = new YamlJavaBeanPropertyConstructor(this.type,          this.propertyAliases);//      加载yaml配置文件      this.configuration = (T) (new Yaml(constructor)).load(this.yaml);      if (this.validator != null) {//        对配置文件进行验证        validate();      }    }    catch (YAMLException ex) {      if (this.exceptionIfInvalid) {        throw ex;      }      logger.error("Failed to load YAML validation bean. "          + "Your YAML file may be invalid.", ex);    }  }

重写了org.springframework.beans.factory.InitializingBean#afterPropertiesSet方法,加载yaml配置文件在对配置文件进行验证

org.springframework.boot.bind.YamlConfigurationFactory#validate

private void validate() throws BindException {    BindingResult errors = new BeanPropertyBindingResult(this.configuration,        "configuration");//    调用验证器对配置文件进行验证    this.validator.validate(this.configuration, errors);    if (errors.hasErrors()) {//      对验证的错误进行处理      logger.error("YAML configuration failed validation");      for (ObjectError error : errors.getAllErrors()) {        logger.error(getErrorMessage(error));      }      if (this.exceptionIfInvalid) {        BindException summary = new BindException(errors);        throw summary;      }    }  }
  @Override  public Class> getObjectType() {    if (this.configuration == null) {      return Object.class;    }    return this.configuration.getClass();  }

重写factoryBean的方法,返回配置类的类型

@Override  public boolean isSingleton() {    return true;  }

返回配置类是否是单例的,这里是单例的

@Override  public T getObject() throws Exception {    if (this.configuration == null) {      afterPropertiesSet();    }    return this.configuration;  }

返回配置类,如果配置类为空就重新加载配置文件

@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Configurationpublic @interface SpringBootConfiguration {}

指示类提供Spring引导应用程序@Configuration。可以作为Spring的标准@Configuration注释的替代,以便自动找到配置(例如在测试中)。应用程序应该只包含一个@SpringBootConfiguration,大多数惯用的Spring引导应用程序将从@SpringBootApplication继承它。

org.springframework.boot.builder.SpringApplicationBuilder SpringApplication配置构造器

applicationprivate final SpringApplication application;

application

private ConfigurableApplicationContext context;

context

private final AtomicBoolean running = new AtomicBoolean(false);

springApplication应用程序是否运行

public SpringApplicationBuilder(Object... sources) {    this.application = createSpringApplication(sources);  }

创建SpringApplication,org.springframework.boot.builder.SpringApplicationBuilder#createSpringApplication 从给定的源创建一个新的SpringApplication实例。子类可以覆盖,以便提供SpringApplication的自定义子类

protected SpringApplication createSpringApplication(Object... sources) {    return new SpringApplication(sources);  }

org.springframework.boot.SpringApplication#SpringApplication(java.lang.Object...) 创建一个新的SpringApplication实例。应用程序上下文将从指定的源加载bean。可以在调用run(String…)之前定制实例。

public SpringApplication(Object... sources) {    initialize(sources);  }

org.springframework.boot.SpringApplication#initialize 初始化

private void initialize(Object[] sources) {    if (sources != null && sources.length > 0) {      this.sources.addAll(Arrays.asList(sources));    }    this.webEnvironment = deduceWebEnvironment();//    加载初始化器 -》    setInitializers((Collection) getSpringFactoriesInstances(        ApplicationContextInitializer.class));//    加载监听器    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));//    根据main方法找出程序的启动类    this.mainApplicationClass = deduceMainApplicationClass();  }

org.springframework.boot.SpringApplication#getSpringFactoriesInstances(java.lang.Class) 加载application初始化器并设置

private  Collection extends T> getSpringFactoriesInstances(Class<T> type) {    return getSpringFactoriesInstances(type, new Class>[] {});  }

org.springframework.boot.SpringApplication#getSpringFactoriesInstances(java.lang.Class, java.lang.Class>[], java.lang.Object...)

private  Collection extends T> getSpringFactoriesInstances(Classtype,      Class>[] parameterTypes, Object... args) {    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();    // Use names and ensure unique to protect against duplicates//    加载META-INF/spring.factories配置的SpringApplicationRunListener监听器    Set<String> names = new LinkedHashSet<String>(        SpringFactoriesLoader.loadFactoryNames(type, classLoader));//    创建META-INF/spring.factories配置的SpringApplicationRunListener监听器对象    List instances = createSpringFactoriesInstances(type, parameterTypes,        classLoader, args, names);    AnnotationAwareOrderComparator.sort(instances);    return instances;  }

org.springframework.core.io.support.SpringFactoriesLoader#loadFactoryNames 加载META-INF/spring.factories这个路径下的类

 public static List<String> loadFactoryNames(Class> factoryClass, ClassLoader classLoader) {        String factoryClassName = factoryClass.getName();        try {            Enumeration ex = classLoader != null?classLoader.getResources("META-INF/spring.factories"):ClassLoader.getSystemResources("META-INF/spring.factories");            ArrayList result = new ArrayList();            while(ex.hasMoreElements()) {                URL url = (URL)ex.nextElement();                Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));                String propertyValue = properties.getProperty(factoryClassName);                String[] var8 = StringUtils.commaDelimitedListToStringArray(propertyValue);                int var9 = var8.length;                for(int var10 = 0; var10 < var9; ++var10) {                    String factoryName = var8[var10];                    result.add(factoryName.trim());                }            }            return result;        } catch (IOException var12) {            throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var12);        }    }

org.springframework.boot.SpringApplication#createSpringFactoriesInstances 创建META-INF/spring.factories路径下的类

private  List createSpringFactoriesInstances(Classtype,      Class>[] parameterTypes, ClassLoader classLoader, Object[] args,      Set<String> names) {    List instances = new ArrayList(names.size());    for (String name : names) {      try {        Class> instanceClass = ClassUtils.forName(name, classLoader);        Assert.isAssignable(type, instanceClass);        Constructor> constructor = instanceClass            .getDeclaredConstructor(parameterTypes);        T instance = (T) BeanUtils.instantiateClass(constructor, args);        instances.add(instance);      }      catch (Throwable ex) {        throw new IllegalArgumentException(            "Cannot instantiate " + type + " : " + name, ex);      }    }    return instances;  }

加载ApplicationContextInitializer、ApplicationListener并初始化设置,根据main方法找到SpringApplication程序启动类

private Class> deduceMainApplicationClass() {    try {      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 null;  }
public ConfigurableApplicationContext run(String... args) {    if (this.running.get()) {      // If already created we just return the existing context 如果已经创建,则返回现有上下文      return this.context;    }    configureAsChildIfNecessary(args);    if (this.running.compareAndSet(false, true)) {      synchronized (this.running) {        // If not already running copy the sources over and then run. 如果还没有运行,复制源代码,然后运行。//        启动spring boot应用程序        this.context = build().run(args);      }    }    return this.context;  }

使用提供的命令行args创建应用程序上下文(如果指定了它的父上下文)。如果尚未启动,则先用相同的参数运行父进程。

public ConfigurableApplicationContext run(String... args) {    if (this.running.get()) {      // If already created we just return the existing context 如果已经创建,则返回现有上下文      return this.context;    }    configureAsChildIfNecessary(args);    if (this.running.compareAndSet(false, true)) {      synchronized (this.running) {        // If not already running copy the sources over and then run. 如果还没有运行,复制源代码,然后运行。//        启动spring boot应用程序        this.context = build().run(args);      }    }    return this.context;  }

运行程序上下文,如果配置的有上一级上下文,先运行上一级上下文

public SpringApplicationBuilder initializers(      ApplicationContextInitializer>... initializers) {    this.application.addInitializers(initializers);    return this;  }

向应用程序添加一些初始化器(在加载任何bean定义之前应用于ApplicationContext)。

public SpringApplicationBuilder listeners(ApplicationListener>... listeners) {    this.application.addListeners(listeners);    return this;  }

向应用程序添加一些侦听器(在上下文运行后侦听SpringApplication事件和常规Spring事件)。任何同时也是ApplicationContextInitializer的侦听器都将自动添加到初始化器中。

org.springframework.boot.CommandLineRunner 接口,用于指示当bean包含在spring应用程序中时它应该运行。可以在相同的应用程序上下文中定义多个CommandLineRunner bean,并且可以使用ordered接口或@Order注释进行排序。如果需要访问ApplicationArguments而不是原始字符串数组,请考虑使用ApplicationRunner。

void run(String... args) throws Exception;

运行CommandLineRunner

org.springframework.boot.ApplicationRunner 接口,用于指示当bean包含在spring应用程序中时它应该运行。可以在相同的应用程序上下文中定义多个ApplicationRunner bean,并且可以使用ordered接口或@Order注释进行排序。

void run(ApplicationArguments args) throws Exception;

运行ApplicationRunner

org.springframework.boot.SpringApplication 类,可用于从Java主方法引导和启动Spring应用程序。默认情况下,类将执行以下步骤来引导您的应用程序:

创建一个适当的ApplicationContext实例(取决于您的类路径),注册一个CommandLinePropertySource,将命令行参数公开为Spring属性,刷新应用程序上下文,加载所有单例bean,触发任何CommandLineRunner bean,spring应用程序可以从各种不同的来源读取bean。一般建议使用单一的@Configuration类来引导应用程序,但是,也可以使用以下任何资源:类——由带注释的beandefinitionreader加载的Java类,Resource—由XmlBeanDefinitionReader加载的XML资源,或者由GroovyBeanDefinitionReader加载的groovy脚本,包——一个由ClassPathBeanDefinitionScanner扫描的Java包,CharSequence——类名、资源句柄或包名。如果不能将CharSequence解析为类,也不能解析为存在的资源,那么它将被视为一个包。

public static final String DEFAULT_CONTEXT_CLASS = "org.springframework.context."      + "annotation.AnnotationConfigApplicationContext";

将默认用于非web环境的应用程序上下文的类名。

public static final String DEFAULT_WEB_CONTEXT_CLASS = "org.springframework."      + "boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext";

web环境默认使用的应用程序上下文的类名。

private static final String[] WEB_ENVIRONMENT_CLASSES = { "javax.servlet.Servlet",      "org.springframework.web.context.ConfigurableWebApplicationContext" };

webApplicationContext

private Class> mainApplicationClass;

springboot程序的运行类

private Banner.Mode bannerMode = Banner.Mode.CONSOLE;

在控制台打印banner

private Banner banner;

banner

private Class extends ConfigurableApplicationContext> applicationContextClass;

applicationContextClass

private List>> initializers;

initializers

private List>> listeners;

listeners

public SpringApplication(Object... sources) {    initialize(sources);  }

创建一个新的SpringApplication实例。应用程序上下文将从指定的源加载bean。可以在调用run(String…)之前定制实例。

org.springframework.boot.SpringApplication#initialize

private void initialize(Object[] sources) {    if (sources != null && sources.length > 0) {      this.sources.addAll(Arrays.asList(sources));    }    this.webEnvironment = deduceWebEnvironment();//    加载初始化器 -》    setInitializers((Collection) getSpringFactoriesInstances(        ApplicationContextInitializer.class));//    加载监听器    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));//    根据main方法找出程序的启动类    this.mainApplicationClass = deduceMainApplicationClass();  }

org.springframework.boot.SpringApplication#getSpringFactoriesInstances(java.lang.Class)

private  Collection extends T> getSpringFactoriesInstances(Class<T> type) {    return getSpringFactoriesInstances(type, new Class>[] {});  }

org.springframework.boot.SpringApplication#getSpringFactoriesInstances(java.lang.Class, java.lang.Class>[], java.lang.Object...)

private  Collection extends T> getSpringFactoriesInstances(Classtype,      Class>[] parameterTypes, Object... args) {    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();    // Use names and ensure unique to protect against duplicates//    加载META-INF/spring.factories配置的SpringApplicationRunListener监听器    Set<String> names = new LinkedHashSet<String>(        SpringFactoriesLoader.loadFactoryNames(type, classLoader));//    创建META-INF/spring.factories配置的SpringApplicationRunListener监听器对象    List instances = createSpringFactoriesInstances(type, parameterTypes,        classLoader, args, names);    AnnotationAwareOrderComparator.sort(instances);    return instances;  }

org.springframework.boot.SpringApplication#createSpringFactoriesInstances

private  List createSpringFactoriesInstances(Classtype,      Class>[] parameterTypes, ClassLoader classLoader, Object[] args,      Set<String> names) {    List instances = new ArrayList(names.size());    for (String name : names) {      try {        Class> instanceClass = ClassUtils.forName(name, classLoader);        Assert.isAssignable(type, instanceClass);        Constructor> constructor = instanceClass            .getDeclaredConstructor(parameterTypes);        T instance = (T) BeanUtils.instantiateClass(constructor, args);        instances.add(instance);      }      catch (Throwable ex) {        throw new IllegalArgumentException(            "Cannot instantiate " + type + " : " + name, ex);      }    }    return instances;  }

从META-INF/spring.factories路径加载ApplicationContextInitializer、ApplicationListener并初始化

org.springframework.boot.SpringApplication#deduceMainApplicationClass 判断有main方法的程序启动类

private Class> deduceMainApplicationClass() {    try {      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 null;  }
public ConfigurableApplicationContext run(String... args) {    StopWatch stopWatch = new StopWatch();    stopWatch.start();    ConfigurableApplicationContext context = null;    FailureAnalyzers analyzers = null;    configureHeadlessProperty();//    初始化SpringApplicationRunListener -》    SpringApplicationRunListeners listeners = getRunListeners(args);//    执行EventPublishingRunListener监听器,广播应用启动事件    listeners.starting();    try {      ApplicationArguments applicationArguments = new DefaultApplicationArguments(          args);      ConfigurableEnvironment environment = prepareEnvironment(listeners,          applicationArguments);//      打印banner      Banner printedBanner = printBanner(environment);//      初始化spring上下文 -》      context = createApplicationContext();      analyzers = new FailureAnalyzers(context);//      准备spring上下文 -》      prepareContext(context, environment, listeners, applicationArguments,          printedBanner);//      刷新spring上下文 -》      refreshContext(context);//      spring上下文初始化完毕加载其他applicationRunner      afterRefresh(context, applicationArguments);//      执行监听器spring加载完成事件      listeners.finished(context, null);      stopWatch.stop();      if (this.logStartupInfo) {        new StartupInfoLogger(this.mainApplicationClass)            .logStarted(getApplicationLog(), stopWatch);      }      return context;    }    catch (Throwable ex) {      handleRunFailure(context, listeners, analyzers, ex);      throw new IllegalStateException(ex);    }  }

启动springboot应用

org.springframework.boot.SpringApplication#getRunListeners 加载并初始化SpringApplicationRunListener

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

org.springframework.boot.SpringApplication#getSpringFactoriesInstances(java.lang.Class, java.lang.Class>[], java.lang.Object...)

  private  Collection extends T> getSpringFactoriesInstances(Classtype,      Class>[] parameterTypes, Object... args) {    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();    // Use names and ensure unique to protect against duplicates//    加载META-INF/spring.factories配置的SpringApplicationRunListener监听器    Set<String> names = new LinkedHashSet<String>(        SpringFactoriesLoader.loadFactoryNames(type, classLoader));//    创建META-INF/spring.factories配置的SpringApplicationRunListener监听器对象    List instances = createSpringFactoriesInstances(type, parameterTypes,        classLoader, args, names);    AnnotationAwareOrderComparator.sort(instances);    return instances;  }

从META-INF/spring.factories路径加载并初始化SpringApplicationRunListener

org.springframework.boot.SpringApplicationRunListeners#starting

public void starting() {    for (SpringApplicationRunListener listener : this.listeners) {      listener.starting();    }  }

调用org.springframework.boot.SpringApplicationRunListener#starting方法。

org.springframework.boot.SpringApplication#createApplicationContext 用于创建应用程序上下文的策略方法。默认情况下,此方法将在返回到合适的默认值之前尊重任何显式设置的应用程序上下文或应用程序上下文类。

protected ConfigurableApplicationContext createApplicationContext() {    Class> contextClass = this.applicationContextClass;    if (contextClass == null) {      try {//        创建基于annotation的上下文对象        contextClass = Class.forName(this.webEnvironment            ? DEFAULT_WEB_CONTEXT_CLASS : DEFAULT_CONTEXT_CLASS);      }      catch (ClassNotFoundException ex) {        throw new IllegalStateException(            "Unable create a default ApplicationContext, "                + "please specify an ApplicationContextClass",            ex);      }    }    return (ConfigurableApplicationContext) BeanUtils.instantiate(contextClass);  }

org.springframework.boot.SpringApplication#prepareContext 准备spring上下文

private void prepareContext(ConfigurableApplicationContext context,      ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,      ApplicationArguments applicationArguments, Banner printedBanner) {    context.setEnvironment(environment);    postProcessApplicationContext(context);//    执行初始化器 =》    applyInitializers(context);//    执行监听器上下文准备事件 -》    listeners.contextPrepared(context);    if (this.logStartupInfo) {      logStartupInfo(context.getParent() == null);      logStartupProfileInfo(context);    }    // Add boot specific singleton beans    context.getBeanFactory().registerSingleton("springApplicationArguments",        applicationArguments);    if (printedBanner != null) {      context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);    }    // Load the sources    Set<Object> sources = getSources();    Assert.notEmpty(sources, "Sources must not be empty");//    加载bean定义 =》    load(context, sources.toArray(new Object[sources.size()]));//    执行spring上线文加载完成事件 -》    listeners.contextLoaded(context);  }

org.springframework.boot.SpringApplication#postProcessApplicationContext 在ApplicationContext中应用任何相关的后处理。子类可以根据需要应用额外的处理。

  protected void postProcessApplicationContext(ConfigurableApplicationContext context) {    if (this.beanNameGenerator != null) {      context.getBeanFactory().registerSingleton(          AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR,          this.beanNameGenerator);    }    if (this.resourceLoader != null) {      if (context instanceof GenericApplicationContext) {        ((GenericApplicationContext) context)            .setResourceLoader(this.resourceLoader);      }      if (context instanceof DefaultResourceLoader) {        ((DefaultResourceLoader) context)            .setClassLoader(this.resourceLoader.getClassLoader());      }    }  }

org.springframework.boot.SpringApplication#applyInitializers 在上下文初始化之前加载ApplicationContextInitializer

protected void applyInitializers(ConfigurableApplicationContext context) {    for (ApplicationContextInitializer initializer : getInitializers()) {      Class> requiredType = GenericTypeResolver.resolveTypeArgument(          initializer.getClass(), ApplicationContextInitializer.class);      Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");      initializer.initialize(context);    }  }

执行org.springframework.context.ApplicationContextInitializer#initialize方法。

org.springframework.boot.SpringApplicationRunListeners#contextPrepared

public void contextPrepared(ConfigurableApplicationContext context) {    for (SpringApplicationRunListener listener : this.listeners) {      listener.contextPrepared(context);    }  }

执行org.springframework.boot.SpringApplicationRunListener#contextPrepared方法。

org.springframework.boot.SpringApplication#load

protected void load(ApplicationContext context, Object[] sources) {    if (logger.isDebugEnabled()) {      logger.debug(          "Loading source " + StringUtils.arrayToCommaDelimitedString(sources));    }//    创建bean定义加载器    BeanDefinitionLoader loader = createBeanDefinitionLoader(        getBeanDefinitionRegistry(context), sources);    if (this.beanNameGenerator != null) {//      设置beanName生成器      loader.setBeanNameGenerator(this.beanNameGenerator);    }    if (this.resourceLoader != null) {      loader.setResourceLoader(this.resourceLoader);    }    if (this.environment != null) {      loader.setEnvironment(this.environment);    }//    加载bean定义 =》    loader.load();  }

加载BeanDefinition

创建BeanDefinition注册器并创建BeanDefinitionLoader

org.springframework.boot.SpringApplication#getBeanDefinitionRegistry 获得BeanDefinition注册器

  private BeanDefinitionRegistry getBeanDefinitionRegistry(ApplicationContext context) {    if (context instanceof BeanDefinitionRegistry) {      return (BeanDefinitionRegistry) context;    }    if (context instanceof AbstractApplicationContext) {      return (BeanDefinitionRegistry) ((AbstractApplicationContext) context)          .getBeanFactory();    }    throw new IllegalStateException("Could not locate BeanDefinitionRegistry");  }

org.springframework.boot.SpringApplication#createBeanDefinitionLoader 创建BeanDefinitionLoader

protected BeanDefinitionLoader createBeanDefinitionLoader(      BeanDefinitionRegistry registry, Object[] sources) {    return new BeanDefinitionLoader(registry, sources);  }

org.springframework.boot.BeanDefinitionLoader#BeanDefinitionLoader

BeanDefinitionLoader(BeanDefinitionRegistry registry, Object... sources) {    Assert.notNull(registry, "Registry must not be null");    Assert.notEmpty(sources, "Sources must not be empty");    this.sources = sources;//    基于注解的BeanDefinitionReader    this.annotatedReader = new AnnotatedBeanDefinitionReader(registry);//    基于xml方式的BeanDefinitionReader    this.xmlReader = new XmlBeanDefinitionReader(registry);    if (isGroovyPresent()) {      this.groovyReader = new GroovyBeanDefinitionReader(registry);    }//    基于classpath路径扫描BeanDefinition的scanner    this.scanner = new ClassPathBeanDefinitionScanner(registry);    this.scanner.addExcludeFilter(new ClassExcludeFilter(sources));  }

org.springframework.boot.BeanDefinitionLoader#load() 加载BeanDefinition

public int load() {    int count = 0;    for (Object source : this.sources) {      count += load(source);    }    return count;  }

org.springframework.boot.BeanDefinitionLoader#load(java.lang.Object)

  private int load(Object source) {    Assert.notNull(source, "Source must not be null");    if (source instanceof Class>) {      return load((Class>) source);    }    if (source instanceof Resource) {      return load((Resource) source);    }//    注解扫描器加载bean定义    if (source instanceof Package) {      return load((Package) source);    }    if (source instanceof CharSequence) {      return load((CharSequence) source);    }    throw new IllegalArgumentException("Invalid source type " + source.getClass());  }

org.springframework.boot.BeanDefinitionLoader#load(java.lang.Class>) 加载配置类的BeanDefinition

private int load(Class> source) {    if (isGroovyPresent()) {      // Any GroovyLoaders added in beans{} DSL can contribute beans here      if (GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {        GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source,            GroovyBeanDefinitionSource.class);        load(loader);      }    }    if (isComponent(source)) {//      注册带有@Configuration的配置类      this.annotatedReader.register(source);      return 1;    }    return 0;  }

org.springframework.boot.BeanDefinitionLoader#load(org.springframework.core.io.Resource) 加载配置文件的BeanDefinition

private int load(Resource source) {    if (source.getFilename().endsWith(".groovy")) {      if (this.groovyReader == null) {        throw new BeanDefinitionStoreException(            "Cannot load Groovy beans without Groovy on classpath");      }//      加载groovy文件的BeanDefinition      return this.groovyReader.loadBeanDefinitions(source);    }//    加载xml文件的BeanDefinition    return this.xmlReader.loadBeanDefinitions(source);  }

org.springframework.boot.BeanDefinitionLoader#load(java.lang.Package) 扫描package类型的BeanDefinition

private int load(Package source) {    return this.scanner.scan(source.getName());  }

加载BeanDefinition相关的过程这里不做详细介绍了,可以查看spring源码解析系列相关文章

org.springframework.boot.SpringApplicationRunListeners#contextLoaded

public void contextLoaded(ConfigurableApplicationContext context) {    for (SpringApplicationRunListener listener : this.listeners) {      listener.contextLoaded(context);    }  }

执行org.springframework.boot.SpringApplicationRunListener#contextLoaded方法。

org.springframework.boot.SpringApplication#refreshContext 刷新ApplicationContext

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

org.springframework.boot.SpringApplication#refresh

protected void refresh(ApplicationContext applicationContext) {    Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);    ((AbstractApplicationContext) applicationContext).refresh();  }

org.springframework.context.support.AbstractApplicationContext#refresh 刷新ApplicationContext,这里的逻辑在这里不详细做介绍,可以查看spring源码解析相关的文章有详细的介绍

org.springframework.boot.SpringApplication#afterRefresh

protected void afterRefresh(ConfigurableApplicationContext context,      ApplicationArguments args) {    callRunners(context, args);  }

ApplicationContext刷新完毕后执行*runners。

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

执行ApplicationRunner的run方法、CommandLineRunner的run方法

org.springframework.boot.SpringApplicationRunListeners#finished ApplicationContext刷新完成方法

public void finished(ConfigurableApplicationContext context, Throwable exception) {    for (SpringApplicationRunListener listener : this.listeners) {      callFinishedListener(listener, context, exception);    }  }

org.springframework.boot.SpringApplicationRunListeners#callFinishedListener

private void callFinishedListener(SpringApplicationRunListener listener,      ConfigurableApplicationContext context, Throwable exception) {    try {      listener.finished(context, exception);    }    catch (Throwable ex) {      if (exception == null) {        ReflectionUtils.rethrowRuntimeException(ex);      }      if (this.log.isDebugEnabled()) {        this.log.error("Error handling failed", ex);      }      else {        String message = ex.getMessage();        message = (message != null) ? message : "no error message";        this.log.warn("Error handling failed (" + message + ")");      }    }  }

执行org.springframework.boot.SpringApplicationRunListener#finished方法。

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

添加ApplicationContextInitializer

public void addInitializers(ApplicationContextInitializer>... initializers) {    this.initializers.addAll(Arrays.asList(initializers));  }

添加ApplicationContextInitialize

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

添加ApplicationListeners

public void addListeners(ApplicationListener>... listeners) {    this.listeners.addAll(Arrays.asList(listeners));  }

添加ApplicationListeners

org.springframework.boot.context.TypeExcludeFilter 实现了org.springframework.beans.factory.BeanFactoryAware接口

提供从BeanFactory加载并自动应用于SpringBootApplication扫描的排除类型筛选器。也可以直接使用@ComponentScan如下:@ComponentScan(excludeFilters = @Filter(type = FilterType)。自定义,class = TypeExcludeFilter.class)),实现应该提供一个用BeanFactory注册的子类,并覆盖match(MetadataReader, MetadataReaderFactory)方法。它们还应该实现一个有效的hashCode和equals方法,以便可以将它们用作Spring test的应用程序上下文缓存的一部分。注意TypeExcludeFilters是在应用程序生命周期的早期初始化的,它们通常不应该依赖于任何其他bean。它们主要用于内部支持spring-boot-test。

private BeanFactory beanFactory;

beanFactory

@Override  public void setBeanFactory(BeanFactory beanFactory) throws BeansException {    this.beanFactory = beanFactory;  }

重写了org.springframework.beans.factory.BeanFactoryAware#setBeanFactory方法,设置beanFactory

@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER,    ElementType.ANNOTATION_TYPE })@Retention(RetentionPolicy.RUNTIME)@Documented@Value("${local.server.port}")public @interface LocalServerPort {}

字段或方法/构造函数参数级别的注释,该参数注入运行时分配的HTTP端口。为@Value(“${local.server.port}”)提供了一个方便的替代方法。

说在最后

本次解析仅代表个人观点,仅供参考。

9ade48adca44a4e7bfb8d7f2122eeb90.gif

扫码进入技术微信群

7c532de64a50fd28a45d95c004bead9f.png 2fdfaccb0667c45f4cf5736a5afddbca.png b7b171a8267646e122d631f62bdda596.png钉钉技术群

bb4002bae94aab86901d322a22665963.png

qq技术群

aacf2c72229ed8533d094506e02580aa.png

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP