Java架构资源分享

Java架构资源分享

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(null, primarySources);}​​​​​​​
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {//设置资源加载器为nullthis.resourceLoader = resourceLoader;//断言加载资源类不能为nullAssert.notNull(primarySources, "PrimarySources must not be null");//将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, null)         && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)         && !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {      return WebApplicationType.REACTIVE;   }   for (String className : SERVLET_INDICATOR_CLASSES) {      if (!ClassUtils.isPresent(className, null)) {         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 null;}

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 = null;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, null);   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 == null) {      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() == 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 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);      }   }}
07-16 23:23