SpringBoot 启动流程

  • 加载 resources/META-INF/spring.factories 中配置的 ApplicationContextInitializer 和 ApplicationListener。
  1. /**
  2. * 加载在框架内部使用的各种通用工厂 bean。
  3. * spring.factories 文件必须满足 Properties 文件格式,属性的 key 是接口或抽象类的全限定类名,
  4. * value 是一组由逗号分隔的实现类全类名。
  5. */
  6. public final class SpringFactoriesLoader {
  7. /**
  8. * 工厂 bean 的搜索路径,可以在多个 jar 文件中出现 spring.factories 文件。
  9. */
  10. public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
  11. private static final Log logger = LogFactory.getLog(SpringFactoriesLoader.class);
  12. private static final Map<ClassLoader, MultiValueMap<String, String>> cache = new ConcurrentReferenceHashMap<>();
  13. private SpringFactoriesLoader() {
  14. }
  15. /**
  16. * 使用给定的类加载器,加载并实例化目标路径 FACTORIES_RESOURCE_LOCATION 下特定接口的实现类,
  17. * 或抽象类的子类。创建的类实例根据 AnnotationAwareOrderComparator 进行排序。
  18. */
  19. public static <T> List<T> loadFactories(Class<T> factoryClass, @Nullable ClassLoader classLoader) {
  20. Assert.notNull(factoryClass, "'factoryClass' must not be null");
  21. ClassLoader classLoaderToUse = classLoader;
  22. if (classLoaderToUse == null) {
  23. classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
  24. }
  25. final List<String> factoryNames = loadFactoryNames(factoryClass, classLoaderToUse);
  26. if (logger.isTraceEnabled()) {
  27. logger.trace("Loaded [" + factoryClass.getName() + "] names: " + factoryNames);
  28. }
  29. final List<T> result = new ArrayList<>(factoryNames.size());
  30. for (final String factoryName : factoryNames) {
  31. result.add(instantiateFactory(factoryName, factoryClass, classLoaderToUse));
  32. }
  33. AnnotationAwareOrderComparator.sort(result);
  34. return result;
  35. }
  36. /**
  37. * 使用指定的类加载器,加载 FACTORIES_RESOURCE_LOCATION 路径下指定类型的 factory 全类名。
  38. */
  39. public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
  40. // 获取目标 factory 全类名
  41. final String factoryClassName = factoryClass.getName();
  42. // 加载所有配置文件,并读取指定 factory 的实现类列表
  43. return loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
  44. }
  45. private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
  46. // 如果已经加载了 spring.factories 文件,则直接从缓存中获取
  47. MultiValueMap<String, String> result = cache.get(classLoader);
  48. if (result != null) {
  49. return result;
  50. }
  51. try {
  52. // 读取资源 URL
  53. final Enumeration<URL> urls = classLoader != null ?
  54. classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
  55. ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION);
  56. result = new LinkedMultiValueMap<>();
  57. while (urls.hasMoreElements()) {
  58. final URL url = urls.nextElement();
  59. final UrlResource resource = new UrlResource(url);
  60. // 将资源加载到 Properties 文件中
  61. final Properties properties = PropertiesLoaderUtils.loadProperties(resource);
  62. for (final Map.Entry<?, ?> entry : properties.entrySet()) {
  63. // 提取 factory 类名称作为 key
  64. final String factoryClassName = ((String) entry.getKey()).trim();
  65. /**
  66. * 将配置的实现类按照 , 分隔,添加到 LinkedMultiValueMap 中。
  67. * 内部通过 LinkedList 管理相同 factory 名称的各种实现类。
  68. */
  69. for (final String factoryName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
  70. result.add(factoryClassName, factoryName.trim());
  71. }
  72. }
  73. }
  74. // 加入缓存
  75. cache.put(classLoader, result);
  76. return result;
  77. }
  78. catch (final IOException ex) {
  79. throw new IllegalArgumentException("Unable to load factories from location [" +
  80. FACTORIES_RESOURCE_LOCATION + "]", ex);
  81. }
  82. }
  83. @SuppressWarnings("unchecked")
  84. private static <T> T instantiateFactory(String instanceClassName, Class<T> factoryClass, ClassLoader classLoader) {
  85. try {
  86. final Class<?> instanceClass = ClassUtils.forName(instanceClassName, classLoader);
  87. if (!factoryClass.isAssignableFrom(instanceClass)) {
  88. throw new IllegalArgumentException(
  89. "Class [" + instanceClassName + "] is not assignable to [" + factoryClass.getName() + "]");
  90. }
  91. return (T) ReflectionUtils.accessibleConstructor(instanceClass).newInstance();
  92. }
  93. catch (final Throwable ex) {
  94. throw new IllegalArgumentException("Unable to instantiate factory class: " + factoryClass.getName(), ex);
  95. }
  96. }
  97. }
  • 加载 resources/META-INF/spring.factories 中配置的 SpringApplicationRunListener
  1. /**
  2. * SpringApplication 监听器,必须提供一个接受命令行参数 String[] 的
  3. * public 构造函数完成实例的初始化。
  4. */
  5. public interface SpringApplicationRunListener {
  6. /**
  7. * 1)加载完 SpringApplicationRunListener 实例后立即执行的方法,在 Application 初始化早期使用。
  8. */
  9. void starting();
  10. /**
  11. * 2)environment 准备好时调用,在 ApplicationContext 创建之前。
  12. */
  13. void environmentPrepared(ConfigurableEnvironment environment);
  14. /**
  15. * 3)在 ApplicationContext 创建并准备好时调用,此时资源还未加载。
  16. */
  17. void contextPrepared(ConfigurableApplicationContext context);
  18. /**
  19. * 4)ApplicationContext 加载完成之后调用,但是 ApplicationContext 还未刷新。
  20. * 组件扫描还未执行,BeanDefinition 还未注册。
  21. */
  22. void contextLoaded(ConfigurableApplicationContext context);
  23. /**
  24. * 5)ApplicationContext 已经刷新并启动,但还未执行 CommandLineRunner 和 ApplicationRunner。
  25. */
  26. void started(ConfigurableApplicationContext context);
  27. /**
  28. * 6)ApplicationContext 已经刷新并启动,所有的CommandLineRunner 和 ApplicationRunner 都已经执行。
  29. */
  30. void running(ConfigurableApplicationContext context);
  31. /**
  32. * 运行此 ApplicationContext 过程中出现异常
  33. */
  34. void failed(ConfigurableApplicationContext context, Throwable exception);
  35. }
  36. /**
  37. * 用于发布 SpringApplicationEvent 的 SpringApplicationRunListener
  38. */
  39. public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {
  40. /**
  41. * 目标应用程序
  42. */
  43. private final SpringApplication application;
  44. /**
  45. * 命令行参数
  46. */
  47. private final String[] args;
  48. /**
  49. * 简单的应用事件广播器
  50. */
  51. private final SimpleApplicationEventMulticaster initialMulticaster;
  52. public EventPublishingRunListener(SpringApplication application, String[] args) {
  53. this.application = application;
  54. this.args = args;
  55. initialMulticaster = new SimpleApplicationEventMulticaster();
  56. for (final ApplicationListener<?> listener : application.getListeners()) {
  57. initialMulticaster.addApplicationListener(listener);
  58. }
  59. }
  60. @Override
  61. public int getOrder() {
  62. return 0;
  63. }
  64. @Override
  65. public void starting() {
  66. initialMulticaster.multicastEvent(
  67. new ApplicationStartingEvent(application, args));
  68. }
  69. @Override
  70. public void environmentPrepared(ConfigurableEnvironment environment) {
  71. initialMulticaster.multicastEvent(new ApplicationEnvironmentPreparedEvent(
  72. application, args, environment));
  73. }
  74. @Override
  75. public void contextPrepared(ConfigurableApplicationContext context) {
  76. initialMulticaster.multicastEvent(new ApplicationContextInitializedEvent(
  77. application, args, context));
  78. }
  79. @Override
  80. public void contextLoaded(ConfigurableApplicationContext context) {
  81. for (final ApplicationListener<?> listener : application.getListeners()) {
  82. if (listener instanceof ApplicationContextAware) {
  83. ((ApplicationContextAware) listener).setApplicationContext(context);
  84. }
  85. context.addApplicationListener(listener);
  86. }
  87. initialMulticaster.multicastEvent(
  88. new ApplicationPreparedEvent(application, args, context));
  89. }
  90. @Override
  91. public void started(ConfigurableApplicationContext context) {
  92. context.publishEvent(
  93. new ApplicationStartedEvent(application, args, context));
  94. }
  95. @Override
  96. public void running(ConfigurableApplicationContext context) {
  97. context.publishEvent(
  98. new ApplicationReadyEvent(application, args, context));
  99. }
  100. @Override
  101. public void failed(ConfigurableApplicationContext context, Throwable exception) {
  102. final ApplicationFailedEvent event = new ApplicationFailedEvent(application,
  103. args, context, exception);
  104. if (context != null && context.isActive()) {
  105. // Listeners have been registered to the application context so we should
  106. // use it at this point if we can
  107. context.publishEvent(event);
  108. }
  109. else {
  110. // An inactive context may not have a multicaster so we use our multicaster to
  111. // call all of the context's listeners instead
  112. if (context instanceof AbstractApplicationContext) {
  113. for (final ApplicationListener<?> listener : ((AbstractApplicationContext) context)
  114. .getApplicationListeners()) {
  115. initialMulticaster.addApplicationListener(listener);
  116. }
  117. }
  118. initialMulticaster.setErrorHandler(new LoggingErrorHandler());
  119. initialMulticaster.multicastEvent(event);
  120. }
  121. }
  122. private static class LoggingErrorHandler implements ErrorHandler {
  123. private static Log logger = LogFactory.getLog(EventPublishingRunListener.class);
  124. @Override
  125. public void handleError(Throwable throwable) {
  126. logger.warn("Error calling ApplicationEventListener", throwable);
  127. }
  128. }
  129. }
  • 创建 StandardServletEnvironment 并完成初始配置。
  1. 1)写入转换服务 ApplicationConversionService.getSharedInstance()
  2. 2)将命令行参数作为属性源加入到 environment.getPropertySources()
  3. 3)写入配置的 AdditionalProfile
  • 通过 EventPublishingRunListener 发布 ApplicationEnvironmentPreparedEvent 事件

  • 加载 resources/META-INF/spring.factories 中配置的 EnvironmentPostProcessor,

    并触发其 postProcessEnvironment 调用,完成 Environment 的后处理【主要用于加载属性源到 Environment 中】。

  • 将 Environment 绑定到 SpringApplication 中。

  • 创建 ApplicationContext:AnnotationConfigServletWebServerApplicationContext

  • 加载 resources/META-INF/spring.factories 中配置的 SpringBootExceptionReporter【FailureAnalyzers】

  • 执行所有已加载的 ApplicationContextInitializer,附加自定义配置。

  • 通过 EventPublishingRunListener 发布 ApplicationContextInitializedEvent 事件

  • 创建 BeanDefinitionLoader,将应用程序主类解析为 BeanDefinition 并注册到 DefaultListableBeanFactory 中。

  1. @Lazy:此 Bean 是否延迟初始化
  2. @DependsOn:此 Bean 是否需要依赖其他 Bean
  3. @Role:此 Bean 的组件角色
  4. @Description:此 Bean 的描述信息
  5. @Scopebean 的代理默认和作用域
  6. @Primary:依赖注入时存在多个候选 bean 时,优先注入此 bean
  • 通过 EventPublishingRunListener 发布 ApplicationPreparedEvent 事件。

刷新此 ApplicationContext: AbstractApplicationContext#refresh()

  1. AbstractApplicationContext#
  2. @Override
  3. public void refresh() throws BeansException, IllegalStateException {
  4. synchronized (startupShutdownMonitor) {
  5. // 1)准备刷新上下文
  6. prepareRefresh();
  7. // 2)通知子类刷新内部的 ConfigurableListableBeanFactory
  8. final ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
  9. // 3)准备在此 ApplicationContext 中使用的 BeanFactory
  10. prepareBeanFactory(beanFactory);
  11. try {
  12. // 4)允许在 ApplicationContext 中对 BeanFactory 进行后处理
  13. postProcessBeanFactory(beanFactory);
  14. // 5)执行注册在当前 ApplicationContext 中的 beanFactory 后处理器
  15. invokeBeanFactoryPostProcessors(beanFactory);
  16. // 6)将 BeanPostProcessor 注册到容器中
  17. registerBeanPostProcessors(beanFactory);
  18. // 7)初始化 MessageSource
  19. initMessageSource();
  20. // 8)初始化 SimpleApplicationEventMulticaster,用于实现事件发布
  21. initApplicationEventMulticaster();
  22. // 9)初始化其他特殊的 bean
  23. onRefresh();
  24. // 10)注册 ApplicationListener
  25. registerListeners();
  26. // 11)实例化所有非延迟的单例类
  27. finishBeanFactoryInitialization(beanFactory);
  28. // 12)清理资源缓存,初始化 LifecycleProcessor,并发布相关事件
  29. finishRefresh();
  30. }
  31. catch (final BeansException ex) {
  32. if (logger.isWarnEnabled()) {
  33. logger.warn("Exception encountered during context initialization - " +
  34. "cancelling refresh attempt: " + ex);
  35. }
  36. // 13)删除已经实例化的单例,避免资源泄漏
  37. destroyBeans();
  38. // 14)设置 active 标识
  39. cancelRefresh(ex);
  40. // 15)传播异常到外部
  41. throw ex;
  42. }
  43. finally {
  44. // 16)重设通用的缓存
  45. resetCommonCaches();
  46. }
  47. }
  48. }
  • prepareRefresh:清除类路径扫描器缓存、写入 closed、active 标识、验证所有必须的属性是否都能解析。

  • obtainFreshBeanFactory:写入 refreshed 标识,获取 DefaultListableBeanFactory。

  • prepareBeanFactory:写入 BeanPostProcessor、写入可以忽略的依赖注入接口,注册部分内部可解析的依赖接口等。

  • postProcessBeanFactory:注册 WebApplicationScope,注册部分内部可解析的依赖接口。

  • invokeBeanFactoryPostProcessors:

    执行 SharedMetadataReaderFactoryContextInitializer$CachingMetadataReaderFactoryPostProcessor

    注册用于获取 MetadataReader 的 org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory 的 BeanDefinition。

  1. 实例化并执行所有的 BeanDefinitionRegistryPostProcessor【内部只注册了 ConfigurationClassPostProcessor】:
  2. 1)执行所有实现 PriorityOrdered 接口的 BeanDefinitionRegistry 后处理器【可以通过自定义 ApplicationContextInitializer 注册】。
  3. 实例化并注册用于解析配置类的解析器【ConfigurationClassPostProcessor】:org.springframework.context.annotation.internalConfigurationAnnotationProcessor
  4. 使用 ConfigurationClassParser 解析主配置类并执行 ComponentScan、执行自动配置类的解析、各种导入 XML 文件的解析,将相关所有类的 BeanDefinition
  5. 注册到 DefaultListableBeanFactory 中。
  6. 2)执行所有实现 Ordered 接口的 BeanDefinitionRegistry 后处理器。
  7. 3)执行所有普通的 BeanDefinitionRegistry 后处理器。
  1. 1)实例化并顺序执行以下内置的 BeanFactoryPostProcessor 后处理器
  2. 无操作:org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer$CachingMetadataReaderFactoryPostProcessor
  3. 无操作:org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer$ConfigurationWarningsPostProcessor
  4. 使用 ConfigurationClassEnhancer 强化所有的配置类:org.springframework.context.annotation.ConfigurationClassPostProcessor
  5. org.springframework.boot.context.config.ConfigFileApplicationListener$PropertySourceOrderingPostProcessor
  6. 2
  7. 执行实现 PriorityOrdered 接口的 BeanFactoryPostProcessor 后处理器。
  8. 执行实现 Ordered 接口的 BeanFactoryPostProcessor 后处理器。
  9. 执行普通的 BeanFactoryPostProcessor 后处理器。
  • registerBeanPostProcessors:

    按照 【PriorityOrdered、Ordered、普通】的顺序将 BeanPostProcessor 添加到 BeanFactory 中。
  1. org.springframework.context.support.ApplicationContextAwareProcessor
  2. org.springframework.boot.web.servlet.context.WebApplicationContextServletContextAwareProcessor org.springframework.context.annotation.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor
  3. org.springframework.context.support.PostProcessorRegistrationDelegate$BeanPostProcessorChecker
  4. org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor
  5. org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator
  6. org.springframework.validation.beanvalidation.MethodValidationPostProcessor
  7. org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor
  8. org.springframework.boot.web.server.WebServerFactoryCustomizerBeanPostProcessor
  9. org.springframework.boot.web.server.ErrorPageRegistrarBeanPostProcessor
  10. org.springframework.context.annotation.CommonAnnotationBeanPostProcessor
  11. org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
  12. org.springframework.context.support.ApplicationListenerDetector
  • initMessageSource:注册 messageSource 单例【DelegatingMessageSource】

  • 注册 applicationEventMulticaster 单例【SimpleApplicationEventMulticaster】,用于广播 ApplicationEvent。

  • onRefresh:设置主题,创建内嵌服务器【WebServer】,获取 ServletContextInitializer【DispatcherServletRegistrationBean】

    初始化器并注册 DispatcherServlet 到 javax.servlet.ServletContext 和 org.apache.catalina.core.ApplicationContext 中。

    注册 OrderedCharacterEncodingFilter、OrderedHiddenHttpMethodFilter、OrderedFormContentFilter、OrderedRequestContextFilter

    等过滤器,也可注册自定义过滤器。

    写入 ServletContextPropertySource、ServletConfigPropertySource 到 Environment 中。

  • registerListeners:注册内置的 ApplicationListener、自定义的 ApplicationListener 到 ApplicationEventMulticaster 中。

  • finishBeanFactoryInitialization:冻结 DefaultListableBeanFactory 中注册的 BeanDefinition 信息,并实例化所有非延迟初始化的单例 bean。

    在所有 eager 单例初始化完成之后,如果其实现了 SmartInitializingSingleton 接口,则触发其 afterSingletonsInstantiated 调用完成后处理。

  1. bean 的实例化过程:
  2. 1)优先实例化所有其依赖的 bean
  3. 2)执行 InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation 预处理,
  4. 如果该方法手动创建了 bean,则直接返回,不进入框架创建 bean 的主流程。
  5. 3)实例化 bean
  6. 4)执行 MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition 后处理,
  7. AutowiredAnnotationBeanPostProcessor:解析 @Autowired@Value@InjectJSR303 注解元数据并缓存。
  8. CommonAnnotationBeanPostProcessor:解析 @PostConstruct@PreDestroy 注解并将目标方法加入 BeanDefinition 中,解析 @Resource 注解元数据并缓存。
  9. 5)将此 bean 加入到 singletonFactories 缓存中,以解决循环依赖问题。
  10. 6)执行 InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation 后处理,
  11. 如果该方法完成了 bean 的依赖属性注入并返回 false,则跳过框架的属性注入流程。
  12. 7)执行 InstantiationAwareBeanPostProcessor#postProcessProperties 依赖属性注入【直接属性注入、set 方法注入】。
  13. @Resource@Autowired@Value@InjectJSR303
  14. 8)执行其他方式的属性依赖注入,如 XML 配置方式。
  15. 9)执行 BeanNameAwareBeanClassLoaderAwareBeanFactoryAware 注入。
  16. 10)触发 BeanPostProcessor#postProcessBeforeInitialization 调用,
  17. ApplicationContextAwareProcessorEnvironmentAwareEmbeddedValueResolverAwareResourceLoaderAwareApplicationEventPublisherAwareMessageSourceAwareApplicationContextAware 注入。
  18. ServletContextAwareProcessorServletContextAwareServletConfigAware 注入。
  19. 11)执行 InitializingBean#afterPropertiesSet 调用,执行自定义的初始化方法。
  20. 12)执行 BeanPostProcessor#postProcessAfterInitialization 调用。
  21. AnnotationAwareAspectJAutoProxyCreator:目标类型上存在 AspectJ 切面注解、目标类型能匹配 Spring 内置的 Advisor【缓存通知、事务处理】,则为目标 bean 创建代理。
  22. MethodValidationPostProcessor:目标类型上存在 @Validated 注解,方法参数或返回类型上存在 JSR303 校验约束,则为目标 bean 创建代理。
  23. PersistenceExceptionTranslationPostProcessor:如果目标类型实现了 org.springframework.dao.support.PersistenceExceptionTranslator 接口,
  24. 则将本地资源异常转换为 DataAccessException
  25. ApplicationListenerDetector:目标 bean 实现了 ApplicationListener 接口,则将其加入到 AbstractApplicationContext.applicationListeners 中。
  • 注册 DefaultLifecycleProcessor,查找所有实现 SmartLifecycle 接口的 bean && 如果它是 isAutoStartup(),则触发其 start() 方法调用。

  • 通过 EventPublishingRunListener 发布 ContextRefreshedEvent 事件。

  • 启动 WebServer。

  • 通过 EventPublishingRunListener 发布 ServletWebServerInitializedEvent 事件。

  • 清理各种缓存

  1. ReflectionUtils.clearCache();
  2. AnnotationUtils.clearCache();
  3. ResolvableType.clearCache();
  4. CachedIntrospectionResults.clearClassLoader(getClassLoader());
  • 注册 Application 的 ShutdownHook。

  • 触发 SpringApplicationRunListener 的 started 通知。

  • 通过 EventPublishingRunListener 发布 ApplicationStartedEvent 事件。

  • 按照 Order 对 ApplicationRunner、CommandLineRunner 进行排序,并顺序执行。

  • 触发 SpringApplicationRunListener 的 running 通知。

  • 通过 EventPublishingRunListener 发布 ApplicationReadyEvent 事件。

  • 应用程序启动完成。

SpringBoot 启动流程的更多相关文章

  1. SpringBoot启动流程解析

    写在前面: 由于该系统是底层系统,以微服务形式对外暴露dubbo服务,所以本流程中SpringBoot不基于jetty或者tomcat等容器启动方式发布服务,而是以执行程序方式启动来发布(参考下图ke ...

  2. SpringBoot启动流程分析(五):SpringBoot自动装配原理实现

    SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...

  3. SpringBoot启动流程分析(六):IoC容器依赖注入

    SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...

  4. SpringBoot启动流程分析(一):SpringApplication类初始化过程

    SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...

  5. SpringBoot启动流程分析(二):SpringApplication的run方法

    SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...

  6. SpringBoot启动流程分析(三):SpringApplication的run方法之prepareContext()方法

    SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...

  7. SpringBoot启动流程分析(四):IoC容器的初始化过程

    SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...

  8. SpringBoot启动流程及其原理

    Spring Boot.Spring MVC 和 Spring 有什么区别? 分别描述各自的特征: Spring 框架就像一个家族,有众多衍生产品例如 boot.security.jpa等等:但他们的 ...

  9. springboot启动流程(一)构造SpringApplication实例对象

    所有文章 https://www.cnblogs.com/lay2017/p/11478237.html 启动入口 本文是springboot启动流程的第一篇,涉及的内容是SpringApplicat ...

随机推荐

  1. Java内存泄漏真实案例

    内存泄漏:当不再需要一个对象时,垃圾收集器会回收它:如果不需要的对象一直在产生而不被收回,就称作“内存泄漏”. 以下为本人在工作中遇到的内存泄漏的案例: 1.对于大量的请求,使用了Executors. ...

  2. 基于mini2440嵌入式Linux根文件系统制作(Initramfs和nfs两种跟文件系统)

    嵌入式系统由三部分构成: 1.bootoader---bootparameters---2.kernel 3.Root-filesysytem 一个内核可以挂载多个文件系统,但是有一个根文件系统所以叫 ...

  3. HDU - 6253 Knightmare (打表+拉格朗日插值)

    题目链接 题意:一个马在无限大的棋盘中跳,问跳n步能跳到多少个不同的格子. 首先写个打表程序打一下n比较小的时候的表: #include<bits/stdc++.h> using name ...

  4. linux学习:【第4篇】之nginx

    一.知识点回顾 临时:关闭当前正在运行的 /etc/init.d/iptables stop 永久:关闭开机自启动 chkonfig iptables off ll /var/log/secure # ...

  5. C# JSON的序列化与反序列化

    需要添加引用:System.ServiceModel.Web 和 System.Runtime.Serialization,然后使用Using: using System.Runtime.Serial ...

  6. CNN简略总结

    https://blog.csdn.net/real_myth/article/details/51824193 池化层的作用: 感受野变化...?? 1*1卷积核的作用 1. 实现跨通道的交互和信息 ...

  7. Nagios-报错:UNKNOWN Can't connect to the JVM:

    原因: 由于手动开启nrpe程序,产生临时文件,需要把产生的多余文件删除. [root@nagios ~]# ll /tmp/drwx------ 3 root root 17 Aug 12 13:4 ...

  8. redis string类型设置过期时间后 再进行set操作,会清除过期时间

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/qq_41756437/article/d ...

  9. 在linux 下配置firewalld

    查看firewalld 是否开始与运行 以下两种方式都可以 systemctl status firewalld.service firewall-cmd --state 查看所有打开的端口 以下两种 ...

  10. 冒泡排序和选择排序(bubble sort and selection sort)

    Bubble sort Basic Method: import random nums = [random.randint(1,20) for _ in range(10)] #制作一个无序数字列表 ...