SpringBoot原理分析

作为一个javaer,和boot打交道是很常见的吧。熟悉boot的人都会知道,启动一个springboot应用,就是用鼠标点一下启动main方法,然后等着就行了。我们来看看这个main里面。

@SpringBootApplication
public class ExampleApplication {
public static void main(String[] args) {
SpringApplication.run(ExampleApplication.class, args);
}
}

这个类很简单吧,有三个注意点。

  • ExampleApplication就是类名,为了规范起见,这个类名一般都是xxxApplication。
  • 有一个注解@SpringBootApplication。
  • 然后就一个main方法,里面使用了SpringApplication的静态方法run(),传进去了俩参数。

这就神奇地启动起来了,为什么呢?

分析的版本:SpringBoot 2.7.18

需要结合以前用xml文件来配置Spring容器的形式来对比Boot用注解的形式

1.注解&自动配置

目前只知道注解的作用即可,至于这些注解是怎么起作用的,见后续...

@SpringBootApplication

这一节来详细聊一聊这个注解。@SpringBootApplication 是 Spring Boot 框架中的一个核心注解,用于简化 Spring Boot 应用的配置和启动

它的作用

  • @SpringBootApplication 标注在应用的主类上,用于启动 Spring Boot 应用。
  • 它启用了 Spring Boot 的自动配置机制,根据项目的依赖自动配置 Spring 应用。
  • 组件扫描:它启用了组件扫描,自动发现并注册带有 @Component@Service@Repository@Controller 等注解的类。
  • 配置类:它标记该类为 Spring 的配置类,相当于 @Configuration 注解。

点进去看看,该注解的结构如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited // 四个元注解
@SpringBootConfiguration
@EnableAutoConfiguration //启用SpringBoot的自动配置机制。SpringBoot会根据类路径中的依赖自动配置应用。例如,如果类路径中有spring-boot-starter-web,SpringBoot会自动配置Tomcat和SpringMVC。 @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) // 启用组件扫描,并排除一些特定的过滤器。默认是注解标注的类所在包及其子包。实际上是不是就是主启动类所在包及其子包!!!!!
public @interface SpringBootApplication {
..............
} // 发现这是一个组合注解

@SpringBootConfiguration 注解:主要作用是标记一个类为 Spring Boot 的配置类与 @Configuration 类似,但它专门用于 Spring Boot 应用。这个注解和@ComponentScan注解结合到一起,达成了如下效果。(左边是xml文件配置形式,右边是SpringBoot注解的形式),这俩注解在一起,就是扫描主启动类所在包及其子包下的被@Controller、@Service、.....标注的类,将他们归到Spring容器里面去。

@EnableAutoConfiguration

@EnableAutoConfiguration注解: 这个注解不得了啊。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class) // 这里。
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
Class<?>[] exclude() default {};
String[] excludeName() default {}; }

发现@Import注解。这个注解的作用是干啥的?这里给出GPT的回答:@Import 是 Spring 框架提供的一个注解,用于将一个或多个配置类(@Configuration 类)组件类导入到当前的 Spring 应用上下文中。它可以用来显式地引入其他配置类或 Bean 定义,从而实现模块化配置和代码复用。

这里有一个非常重要的东西,那就是当前的Spring上下文,也就是主启动类所在包及其子包,@Import(AutoConfigurationImportSelector.class)这句话的意思是将SpringBoot官方写的AutoConfigurationImportSelector类导入到当前Spring上下文中,在当前Spring上下文注册这样一个bean。

AutoConfigurationImportSelector探究

public interface ImportSelector {
String[] selectImports(AnnotationMetadata importingClassMetadata);
}
// 实现了DeferredImportSelector接口,DeferredImportSelector实现了ImportSelector
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
...........
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata); // 1.进去
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
} // 2.这个方法
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 3.进入这里
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
...........
} // 4. 3调用的这个方法
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = new ArrayList<>(
// 5. 继续往下
SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()));
ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader()).forEach(configurations::add);
Assert.notEmpty(configurations,
"No auto configuration classes found in META-INF/spring.factories nor in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you "
+ "are using a custom packaging, make sure that file is correct.");
return configurations;
} // 6. 5处调用的方法
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
...... // loadSpringFactories
return loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());
} // 7
// 最终可以在loadSpringFactories方法里面看到这样一行代码
//Enumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION);
// public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
// 结合官方给的解释The location to look for factories. Can be present in multiple JAR files. 寻找工厂的位置。可以存在于多个 JAR 文件中。
}

结合idea打断点调试:我们发现getCandidateConfigurations扫描到了引入的所有jar包的META-INF/spring.factories,共有156个xxxAutoConfigure类。但是这些都会用到吗,别忘了,SpringBoot有个非常强大的特点:那就是导入场景、对应的场景才会生效!!

继续往下走,请看下图:(发现只有50个了,例如上图里面的amqp,由于项目中没有用到,故在这里就没有了,经过了filter过滤)

以RabbitMq自动配置为例

@AutoConfiguration
@ConditionalOnClass({ RabbitTemplate.class, Channel.class }) // 这两个类存在时才生效,项目里面没导入相关jar包,故RabbitAutoConfiguration不会被导入Spring容器生效,下面就来说这个注解
@EnableConfigurationProperties(RabbitProperties.class)
@Import({ RabbitAnnotationDrivenConfiguration.class, RabbitStreamConfiguration.class })
public class RabbitAutoConfiguration {
................
}

@ConditionalOnClass

先看看其源码

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnClassCondition.class) // 这里***
public @interface ConditionalOnClass {
Class<?>[] value() default {};
String[] name() default {};
}

@ConditionalOnClass注解的作用是当项目中存在某个类时才会使标有该注解的类或方法生效;

先看我们的主类【1. 此时,没有引入test.demo.test.list.Student所在的maven依赖】

/* 下面是这俩类
public class Cat {
private Integer id;
private String name;
}
public class Dog {
private Integer id;
private String name;
}*/ @SpringBootApplication
@MapperScan("com.feng.tackle.dao")
public class DateApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(DateApplication.class, args);
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
Iterator<String> iterator = beanFactory.getBeanNamesIterator();
while (iterator.hasNext()) {
String name = iterator.next();
if ( name.equals("dog01") || name.equals("cat01") ) System.out.println(name); // 看看有没有这两个名字的bean
}
}
}
// 最后的输出结果
/*
cat01
*/

在配置类中,我们这样做

@Configuration
public class ConditionTestConfig {
@ConditionalOnClass(name = "test.demo.test.list.Student") // 类路径有这个类,就往容器中放入该bean
@Bean
public Dog dog01() {
return new Dog(2, "汪汪汪");
} @ConditionalOnMissingClass("test.demo.test.list.Student") // 类路径没有这个类,就往容器中放入该bean
@Bean
public Cat cat01() {
return new Cat(1, "喵喵喵");
}
}

main最后的输出结果是cat01。"test.demo.test.list.Student"是另一个maven项目里面的类。

【2. 项目中引入Student所在的maven】

<dependency>
<groupId>com.feng.test</groupId>
<artifactId>test-demo</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>

再次启动main,输出结果dog01

通过这个例子,我们可以知道SpringBoot自动配置,导入具体starter,对应的场景才会生效。【由于没有导入MQ的starter,故此配置类不会生效】

总结

**自动配置: **

以spring-boot-starter-web为例子,引入该启动器,他的父级pom里面有spring-boot-starter,spring-boot-starter的父级pom有spring-boot-autoconfigure。

spring-boot-autoconfigure里面有Spring官方定义的所有场景。

  • @EnableAutoConfiguration 注解:这是自动配置的入口,通常由 @SpringBootApplication 注解组合引入。
  • spring.factories 文件:Spring Boot 通过 META-INF/spring.factories 文件加载自动配置类。
  • 条件化配置:通过 @Conditional 系列注解(如 @ConditionalOnClass@ConditionalOnMissingBean 等)实现按需加载配置。

自动配置的流程:

  1. 加载自动配置类
  • @SpringBootApplication 注解:该注解是一个组合注解,包含了 @EnableAutoConfiguration,用于启用自动配置。
  • @EnableAutoConfiguration 的作用:该注解会通过 SpringFactoriesLoader 加载 META-INF/spring.factories 文件中定义的自动配置类。
  1. 条件化配置

自动配置类通常使用 @Conditional 系列注解来控制是否生效

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@ConditionalOnMissingBean(type = "io.r2dbc.spi.ConnectionFactory")
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({ DataSourcePoolMetadataProvidersConfiguration.class, DataSourceInitializationConfiguration.class })
public class DataSourceAutoConfiguration {
// 自动配置逻辑
}
//如果类路径中存在 DataSource 和 EmbeddedDatabaseType,且容器中没有 ConnectionFactory Bean,则自动配置 DataSource。
  1. 加载配置属性
  • @EnableConfigurationProperties:自动配置类通常会通过该注解加载配置属性。
  • application.propertiesapplication.yml:Spring Boot 会读取这些配置文件中的属性,并将其绑定到对应的配置类中。
@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceProperties {
private String url;
private String username;
private String password;
// getters and setters
}
  1. 注册bean
  • 自动配置类通过 @Bean 方法向容器中注册 Bean。
  • 这些 Bean 通常是框架的核心组件,如 DataSourceDispatcherServletSecurityFilterChain 等。

2. 启动过程

SpringApplication.run(ExampleApplication.class, args);这一行代码做了啥?这才是重点!

从run开始看,一层一层往下面点进去

// 1.
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) { // 会返回一个正在运行的Spring容器
return run(new Class<?>[] { primarySource }, args); // 调用重载的run方法
}
// 2.
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return new SpringApplication(primarySources).run(args); // 先调用该构造方法,然后再调用run方法,将程序参数传进去
}
// 3.
public SpringApplication(Class<?>... primarySources) {
this(null, primarySources); //primarySource 是传入的主配置类(通常带有 @SpringBootApplication 注解的类),Spring Boot 会将其作为配置源。
} // 4. [构造方法] 构造方法
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
........ // 见下一节构造方法
}

先调用该构造方法,然后再调用run方法

①构造方法

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader; // null的
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources)); // 一、设置主配置类
this.webApplicationType = WebApplicationType.deduceFromClasspath(); // 二、推断应用类型
this.bootstrapRegistryInitializers = new ArrayList<>( // 三、
getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));// 四、
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));// 五、
this.mainApplicationClass = deduceMainApplicationClass(); // 六、通过堆栈信息推断出主类(即 main 方法所在的类)。
}

1.推断应用类型

  • WebApplicationType.deduceFromClasspath() 方法会根据类路径中是否存在特定的类来推断应用类型。
  • 可能的类型包括:
    • WebApplicationType.SERVLET:基于 Servlet 的 Web 应用(如 Spring MVC)。
    • WebApplicationType.REACTIVE:基于 Reactive 的 Web 应用(如 Spring WebFlux)。
    • WebApplicationType.NONE:非 Web 应用。

2.加载并初始化 BootstrapRegistryInitializer 实例

分析一下核心方法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;
} // SpringFactoriesLoader.loadFactoryNames(type, classLoader) 到这儿来了
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
ClassLoader classLoaderToUse = classLoader;
if (classLoaderToUse == null) {
classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
}
String factoryTypeName = factoryType.getName();
return loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());
} //loadSpringFactories(classLoaderToUse)
private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
// static final Map<ClassLoader, Map<String, List<String>>> cache = new ConcurrentReferenceHashMap<>();
// 从缓存map中拿到对应classLoader的map,如果该classLoader已经存在了,就不用走下面的了
Map<String, List<String>> result = cache.get(classLoader);
if (result != null) {
return result;
} result = new HashMap<>();
try {
/*
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
结合官方给的解释The location to look for factories. Can be present in multiple JAR files. 寻找工厂的位置。可以存在于多个 JAR 文件中。
*/
Enumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION);
..............
return result;
}

可以看到这里,在第一章《注解&自动配置》也出现了这个,如今在SpringApplication的构造方法,底层也调用到了这里。二者有什么区别或者联系呢?

SpringFactoriesLoader.loadFactoryNames是Spring Boot 提供的工具方法,用于从 META-INF/spring.factories 文件中加载指定类型的配置类。

两者都依赖于 META-INF/spring.factories 文件,该文件是 Spring Boot 自动配置和扩展机制的核心配置文件。两者都通过类路径扫描,加载所有 META-INF/spring.factories 文件,并解析出指定类型的配置类。

(1)调用位置

  • AutoConfigurationImportSelector

    • 位于 org.springframework.boot.autoconfigure 包中。
    • 是 Spring Boot 自动配置的核心组件之一,负责加载自动配置类。
    • 在 Spring 容器的配置类解析阶段被调用(具体是在 @EnableAutoConfiguration 注解的处理过程中)。
  • SpringApplication
    • 位于 org.springframework.boot 包中。
    • 是 Spring Boot 应用的启动类,负责初始化应用上下文、加载配置等。
    • 在应用启动时被调用。

(2)加载的配置类型

  • AutoConfigurationImportSelector

    • 主要加载 META-INF/spring.factories 文件中 org.springframework.boot.autoconfigure.EnableAutoConfiguration 键下的自动配置类。
    • 这些配置类用于实现 Spring Boot 的自动配置功能(如 DataSourceAutoConfigurationWebMvcAutoConfiguration 等)。
  • SpringApplication
    • 加载多种类型的配置类,包括:

      • ApplicationContextInitializer
      • ApplicationListener
      • BootstrapRegistryInitializer
    • 这些配置类用于初始化应用上下文、监听应用事件等。

(3)调用时机

  • AutoConfigurationImportSelector

    • 在 Spring 容器解析配置类时调用(具体是在 ConfigurationClassPostProcessor 处理 @Configuration 类时)。
    • 属于 Spring 容器初始化的早期阶段。
  • SpringApplication
    • 在应用启动时调用(具体是在 SpringApplication 的构造方法或 run 方法中)。
    • 属于应用启动的早期阶段。

(4)返回值的使用

  • AutoConfigurationImportSelector

    • 返回的自动配置类会被 Spring 容器加载并处理,最终生成相应的 Bean 定义。
    • 这些配置类通常包含 @Configuration 注解和 @Conditional 注解,用于按需加载 Bean。
  • SpringApplication
    • 返回的配置类会被直接实例化并注册到应用中。
    • 例如,ApplicationContextInitializer 会被调用以初始化应用上下文,ApplicationListener 会被注册以监听应用事件。

3.加载并设置 ApplicationContextInitializer 实例

同2

4.加载并设置 ApplicationListener 实例

同2

总结

  • BootstrapRegistryInitializer:用于应用启动的最早阶段,初始化引导阶段的组件。
  • ApplicationContextInitializer:用于在 ApplicationContext 创建之后、刷新之前,对上下文进行自定义初始化。
  • ApplicationListener:用于监听应用生命周期中的事件,并在特定阶段执行逻辑。

这三者共同扩展了 Spring Boot 应用的启动过程,提供了灵活的扩展点,可以满足不同场景下的需求。

5.三者的实现

分别编写实现类

public class MyBootstrapInit implements BootstrapRegistryInitializer {
@Override
public void initialize(BootstrapRegistry registry) {
System.out.println("【MyBootstrapInit】--------------方法执行了");
}
} public class MyApplicationContextInit implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
System.out.println("【MyApplicationContextInit】------------" + applicationContext.getApplicationName());
}
} public class MyContextListener implements ApplicationListener<ApplicationStartedEvent> { // 该监听器对此事件感兴趣
@Override
public void onApplicationEvent(ApplicationStartedEvent event) {
System.out.println("【MyContextListener】--监听器--" + event.getSource());
}
}

然后在resource目录下面创建META-INF,在其中的spring.factories中

org.springframework.boot.BootstrapRegistryInitializer=com.feng.tackle.config.source.MyBootstrapInit
org.springframework.context.ApplicationContextInitializer=com.feng.tackle.config.source.MyApplicationContextInit
org.springframework.context.ApplicationListener=com.feng.tackle.config.source.MyContextListener

启动应用:

疑问? 我可以在这三者的实现类上面加@Configuration注解,不要spring.factories,可以实现类似效果吗?

答案是,只有ApplicationListener可以。为什么?请看下面的run方法里面

②run

public ConfigurableApplicationContext run(String... args) {
// 记录应用启动的开始时间,用于后续计算启动耗时。
long startTime = System.nanoTime();
//创建一个 BootstrapContext,用于在应用启动的早期阶段提供一些基础设施支持(如环境配置、属性源等)================
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
// 设置系统属性 java.awt.headless,确保应用在没有图形界面环境(如服务器)中也能正常运行
configureHeadlessProperty();
/*
获取所有 SpringApplicationRunListener 实例,用于监听应用启动的各个阶段。调用 listeners.starting(),通知监听器应用正在启动。
*/
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 加载和配置应用的环境(Environment),包括配置文件(如 application.properties 或 application.yml)、命令行参数等。
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
configureIgnoreBeanInfo(environment);
// 打印 Spring Boot 的启动 Banner(默认或自定义)。
Banner printedBanner = printBanner(environment);
// 根据应用类型(Servlet、Reactive 等)创建相应的 ApplicationContext。
context = createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
// 准备应用上下文
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
// 调用 AbstractApplicationContext.refresh() 方法,完成 Bean 的实例化、依赖注入和初始化。
refreshContext(context);
afterRefresh(context, applicationArguments);
// 计算启动耗时并记录日志。
Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
}
listeners.started(context, timeTakenToStartup);
// 执行所有 ApplicationRunner 和 CommandLineRunner 的实现类,用于在应用启动后执行自定义逻辑。
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
// 计算应用启动到就绪的总耗时。
Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
listeners.ready(context, timeTakenToReady);
}
catch (Throwable ex) {
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
return context;
}

这个run这里分析得不够深入。受篇幅影响,在后续文章中再来分析。

end. 参考

  1. 尚硅谷雷丰阳老师的课

SpringBoot原理分析-1的更多相关文章

  1. SpringBoot原理分析与配置

    1.1 起步依赖原理分析 1.1.1 分析spring-boot-starter-parent 按住Ctrl点击pom.xml中的spring-boot-starter-parent,跳转到了spri ...

  2. SpringBoot原理—分析SpringBoot启动机制(starter机制)

    一:前言使用过springboot的同学应该已经知道,springboot通过默认配置了很多框架的使用方式帮我们大大简化了项目初始搭建以及开发过程.本文的目的就是一步步分析springboot的启动过 ...

  3. SpringBoot 原理分析、监控、项目部署

    目录 SpringBoot 监控 概述 使用 SpringBoot Admin 概述 使用 SpringBoot 项目部署 SpringBoot 监控 概述 SpringBoot 自带监控功能 Act ...

  4. SpringBoot入门(0) HelloWorld的实现与原理分析

    SpringBoot(0) HelloWorld的实现与原理分析 一.环境准备 1.1 环境约束 –jdk1.8:Spring Boot 推荐jdk1.7及以上:java version “1.8.0 ...

  5. springboot创建,自动装配原理分析,run方法启动

    使用IDEA快速创建一个springboot项目 创建Spring Initializr,然后一直下一步下一步直至完成 选择web,表示创建web项目 运行原理分析 我们先来看看pom.xml文件 核 ...

  6. SpringBoot(概述、起步依赖原理分析、SpringBoot配置(配置文件分类、YAML))

    SpringBoot概述 Spring Boot 是由 Pivotal 团队提供用来简化 Spring 的搭建和开发过程的全新框架.随着近些年来微服务技术的流行,Spring Boot 也成了时下炙手 ...

  7. 深入springboot原理——动手封装一个starter

    从上一篇文章<深入springboot原理——一步步分析springboot启动机制(starter机制)> 我们已经知道springboot的起步依赖与自动配置的机制.spring-bo ...

  8. spring boot 运行jsp原理分析

    Spring-boot运行jsp原理分析   结论: 启动server的时候会创建临时目录 在浏览器中访问jsp文件的时候通过内置Tomcat将jsp转换为java,保存在临时目录中 然后编译为cla ...

  9. SpringBoot原理发现(一)

    说明: 本系列基于SpringBoot 2.2.9.RELEASE 版本,对SpringBoot的原理进行分析,一共分为四节: SpringBoot原理发现(一):创建Hello World,对pom ...

  10. Spring Cloud之负载均衡组件Ribbon原理分析

    目录 前言 一个问题引发的思考 Ribbon的简单使用 Ribbon 原理分析 @LoadBalanced 注解 @Qualifier注解 LoadBalancerAutoConfiguration ...

随机推荐

  1. 即时通讯技术文集(第35期):IM群聊技术合集(Part2) [共12篇]

    为了更好地分类阅读 52im.net 总计1000多篇精编文章,我将在每周三推送新的一期技术文集,本次是第35 期. ​[- 1 -] 直播系统聊天技术(一):百万在线的美拍直播弹幕系统的实时推送技术 ...

  2. Appium_iOS_Safari测试脚本(2)

    经过多次调试,在Safari上的测试脚本终于可以运行了,不过部分元素还是无法识别,还需要继续调试: #!/usr/bin/env/python # -*-coding:utf-8-*- import ...

  3. CDS标准视图:维护项目数据 C_MaintenanceItemDEX

    视图名称:维护项目数据 C_MaintenanceItemDEX 视图类型:基础 视图代码: 点击查看代码 @AbapCatalog.sqlViewName: 'CMAINTITEMDEX' @Aba ...

  4. tomcat常用配置详解和优化方法-copy

    tomcat常用配置详解和优化方法 参考: http://blog.csdn.net/zj52hm/article/details/51980194 http://blog.csdn.net/wuli ...

  5. mac系统如何安装nacos

    一:安装步骤1.先到nacos官网nacos.iohttp://nacos.io/ 2.点击开源版(进去下拉文档,找到 latest stable release 点进去) 3.点击下载zip文件到本 ...

  6. kubernetes 使用ceph实现动态持久卷存储

    k8s使用ceph存储 ceph提供底层存储功能,cephfs方式支持k8s的pv的3种访问模式​​ReadWriteOnce,ReadOnlyMany ,ReadWriteMany​​​ ,RBD支 ...

  7. 基于Fluss 的流式湖仓架构

    目录 1. What 2. 架构 2.1 CoordinatorServer 2.2 TabletServer 2.3 LogStore 2.4 KvStore 2.5 Tablet / Bucket ...

  8. 学习shamir秘密分享

    介绍 1979年Shamir在下文提出基于拉格朗日插值多项式的\((r,n)\)秘密共享方案(\(0<r \leq n\)).秘密拥有者通过构建一元多项式将秘密分为\(n\)份,接收方收集大于等 ...

  9. MySQL插入修改和删除

    原文链接:https://blog.liuzijian.com/post/36d9bcaa-2ba7-26ca-6f97-b8ef7a058e95.html 插入 支持一次性插入多行,支持子查询 IN ...

  10. 2024大湾区网络安全大会,AOne来了!

    近日,2024大湾区网络安全大会暨第二十六期花城院士科技会议在广州启幕.学者专家.高校院长.政府相关负责人及行业大咖齐聚一堂,围绕网络安全的前沿话题与挑战展开深入交流与探讨.天翼云科技有限公司网络安全 ...