SpringBoot原理分析-1
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等)实现按需加载配置。
自动配置的流程:
- 加载自动配置类
@SpringBootApplication注解:该注解是一个组合注解,包含了@EnableAutoConfiguration,用于启用自动配置。@EnableAutoConfiguration的作用:该注解会通过SpringFactoriesLoader加载META-INF/spring.factories文件中定义的自动配置类。
- 条件化配置
自动配置类通常使用 @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。
- 加载配置属性
@EnableConfigurationProperties:自动配置类通常会通过该注解加载配置属性。application.properties或application.yml:Spring Boot 会读取这些配置文件中的属性,并将其绑定到对应的配置类中。
@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceProperties {
private String url;
private String username;
private String password;
// getters and setters
}
- 注册bean
- 自动配置类通过
@Bean方法向容器中注册 Bean。 - 这些 Bean 通常是框架的核心组件,如
DataSource、DispatcherServlet、SecurityFilterChain等。
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 的自动配置功能(如
DataSourceAutoConfiguration、WebMvcAutoConfiguration等)。
- 主要加载
SpringApplication:- 加载多种类型的配置类,包括:
ApplicationContextInitializerApplicationListenerBootstrapRegistryInitializer
- 这些配置类用于初始化应用上下文、监听应用事件等。
- 加载多种类型的配置类,包括:
(3)调用时机
AutoConfigurationImportSelector:- 在 Spring 容器解析配置类时调用(具体是在
ConfigurationClassPostProcessor处理@Configuration类时)。 - 属于 Spring 容器初始化的早期阶段。
- 在 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. 参考
- 尚硅谷雷丰阳老师的课
SpringBoot原理分析-1的更多相关文章
- SpringBoot原理分析与配置
1.1 起步依赖原理分析 1.1.1 分析spring-boot-starter-parent 按住Ctrl点击pom.xml中的spring-boot-starter-parent,跳转到了spri ...
- SpringBoot原理—分析SpringBoot启动机制(starter机制)
一:前言使用过springboot的同学应该已经知道,springboot通过默认配置了很多框架的使用方式帮我们大大简化了项目初始搭建以及开发过程.本文的目的就是一步步分析springboot的启动过 ...
- SpringBoot 原理分析、监控、项目部署
目录 SpringBoot 监控 概述 使用 SpringBoot Admin 概述 使用 SpringBoot 项目部署 SpringBoot 监控 概述 SpringBoot 自带监控功能 Act ...
- SpringBoot入门(0) HelloWorld的实现与原理分析
SpringBoot(0) HelloWorld的实现与原理分析 一.环境准备 1.1 环境约束 –jdk1.8:Spring Boot 推荐jdk1.7及以上:java version “1.8.0 ...
- springboot创建,自动装配原理分析,run方法启动
使用IDEA快速创建一个springboot项目 创建Spring Initializr,然后一直下一步下一步直至完成 选择web,表示创建web项目 运行原理分析 我们先来看看pom.xml文件 核 ...
- SpringBoot(概述、起步依赖原理分析、SpringBoot配置(配置文件分类、YAML))
SpringBoot概述 Spring Boot 是由 Pivotal 团队提供用来简化 Spring 的搭建和开发过程的全新框架.随着近些年来微服务技术的流行,Spring Boot 也成了时下炙手 ...
- 深入springboot原理——动手封装一个starter
从上一篇文章<深入springboot原理——一步步分析springboot启动机制(starter机制)> 我们已经知道springboot的起步依赖与自动配置的机制.spring-bo ...
- spring boot 运行jsp原理分析
Spring-boot运行jsp原理分析 结论: 启动server的时候会创建临时目录 在浏览器中访问jsp文件的时候通过内置Tomcat将jsp转换为java,保存在临时目录中 然后编译为cla ...
- SpringBoot原理发现(一)
说明: 本系列基于SpringBoot 2.2.9.RELEASE 版本,对SpringBoot的原理进行分析,一共分为四节: SpringBoot原理发现(一):创建Hello World,对pom ...
- Spring Cloud之负载均衡组件Ribbon原理分析
目录 前言 一个问题引发的思考 Ribbon的简单使用 Ribbon 原理分析 @LoadBalanced 注解 @Qualifier注解 LoadBalancerAutoConfiguration ...
随机推荐
- DotNetBar控件中,删除或移除AdvTree上指定名称的Node
废话少说,直接上核心代码: string deleteNodeName = "节点1"; //移除advTree上指定名称的Node Node deleteNode = advTr ...
- 单片机的主程序中为什么都要加一个while(1)?
*** * C51 为什么都要加一个while(1)?****** while(1)的作用: while(1) 是一个死循环 为了不让代码继续向下执行. 单片机中使用while(1),大部分:为了防止 ...
- 2021 年万圣节 Github 彩蛋
记录每年 Github 万圣节彩蛋,也记录有来项目成长历程. 2021 万圣节彩蛋 2020 万圣节彩蛋
- Docker Inspect 模板
Docker 使用Go 模板,您可以使用它来操作某些命令和日志驱动程序的输出格式. Docker 提供了一组基本函数来操作模板元素.所有这些示例都使用该docker inspect命令,但许多其他 C ...
- 第三章 dubbo源码解析目录
7.6 服务远程暴露 - 注册服务到zookeeper 为了安全:服务启动的ip全部使用10.10.10.10 远程服务的暴露总体步骤: 将ref封装为invoker 将invoker转换为expor ...
- javascript对象学习笔记
目前所见的,在普通的JavaScript应用中和绝大多数人一样使用的是全局的方式.大概是因为JavaScript所定义的变量或函数默认就是全局的.为了是代码不至于太凌乱,变量不至于稀里糊涂的就被人重定 ...
- [rustGUI][iced]基于rust的GUI库iced(0.13)的部件学习(05):svg图片转为png格式(暨svg部件的使用)
前言 本文是关于iced库的部件介绍,iced库是基于rust的GUI库,作者自述是受Elm启发. iced目前的版本是0.13.1,相较于此前的0.12版本,有较大改动. 本合集是基于新版本的关于分 ...
- ORACLE 中报ORA-30926 无法在源表中获得稳定的行的处理
在库存处理的业务中有这么一个场景,一张处方划价单进行库存扣减处理,如果此单据同一商品有两行以上,同时扣减同一行库存记录,使用MERGE INTO批量更新是就会报错:ORA-30926 无法在源表中获得 ...
- ORACLE 分页和行限制
行限制:示例 (此语法从12C版本开始支持) 以下语句返回具有最低employee_id值的 5 名员工: SELECT employee_id, last_name FROM Employees O ...
- 【SQL跟踪工具】SQL Profiler 跟踪器使用
阅读目录 什么是SQL Profiler 为什么要使用SQL Profiler 如何使用SQL Profiler 什么是SQL Profiler SQL Server Profiler 是一个功能丰富 ...