入理解 SpringBoot 启动机制(starter 机制)

2023-05-16

深入理解 SpringBoot 启动机制(starter 机制)

  • 一、前言
  • 二、起步依赖
  • 三、自动配置
    • 1.基于java代码的bean配置
    • 2.自动配置条件依赖
    • 3.Bean参数的获取
    • 3.Bean的发现
    • 4.Bean 加载
  • 四、总结

  • 《Java 2019 超神之路》
  • 《Dubbo 实现原理与源码解析 —— 精品合集》
  • 《Spring 实现原理与源码解析 —— 精品合集》
  • 《MyBatis 实现原理与源码解析 —— 精品合集》
  • 《Spring MVC 实现原理与源码解析 —— 精品合集》
  • 《Spring Boot 实现原理与源码解析 —— 精品合集》
  • 《数据库实体设计合集》
  • 《Java 面试题 —— 精品合集》
  • 《Java 学习指南 —— 精品合集》

一、前言

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

那么首先带领大家回顾一下以往我们的web项目是如何搭建的,通常我们要搭建一个基于Spring的Web应用,我们需要做以下一些工作:

1、pom文件中引入相关jar包,包括spring、springmvc、redis、mybaits、log4j、mysql-connector-java 等等相关jar ...

2、配置web.xml,Listener配置、Filter配置、Servlet配置、log4j配置、error配置 ...

3、配置数据库连接、配置spring事务

4、配置视图解析器

5、开启注解、自动扫描功能

6、配置完成后部署tomcat、启动调试 ......

花在搭建一个初始项目,可能一个小时就过去了或者半天救过了,但是用了SpringBoot之后一切都会变得非常便捷,下面我们首先来分析一下SpringBoot的起步依赖以及自动配置。

二、起步依赖

1.在我们的pom文件里面引入以下jar:

<modelVersion>4.0.0</modelVersion>
   <parent>
   	<groupId>org.springframework.boot</groupId>
   	<artifactId>spring-boot-starter-parent</artifactId>
   	<version>2.0.4.RELEASE</version>
   	<relativePath /><!-- lookup parent from repository -->
   </parent>
   <groupId>com.example</groupId>
   <artifactId>demo</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <name>demo</name>
   <description>Demo project for Spring Boot</description>

   <properties>
   	<java.version>1.8</java.version>
   </properties>

   <dependencies>
   	<dependency>
   		<groupId>org.springframework.boot</groupId>
   		<artifactId>spring-boot-starter-web</artifactId>
   	</dependency>

   	<dependency>
   		<groupId>org.springframework.boot</groupId>
   		<artifactId>spring-boot-starter-test</artifactId>
   		<scope>test</scope>
   	</dependency>

   	<!--mybatis 开发包 -->
   	<dependency>
   		<groupId>org.mybatis.spring.boot</groupId>
   		<artifactId>mybatis-spring-boot-starter</artifactId>
   		<version>1.3.2</version>
   	</dependency>
   	<!--springboot web模块支持 -->
   	<dependency>
   		<groupId>org.springframework.boot</groupId>
   		<artifactId>spring-boot-starter-web</artifactId>
   	</dependency>
   	<dependency>
   		<groupId>mysql</groupId>
   		<artifactId>mysql-connector-java</artifactId>
   		<scope>runtime</scope>
   	</dependency>
   </dependencies>

   <build>
   	<plugins>
   		<plugin>
   			<groupId>org.springframework.boot</groupId>
   			<artifactId>spring-boot-maven-plugin</artifactId>
   		</plugin>
   	</plugins>
   </build>

spring-boot-starter-web包自动帮我们引入了web模块开发需要的相关jar包。mybatis-spring-boot-starter帮我们引入了dao开发相关的jar包。spring-boot-starter-xxx是官方提供的starter,xxx-spring-boot-starter是第三方提供的starter。截图看一下我们的mybatis-spring-boot-starter

 

 

可以看出mybatis-spring-boot-starter并没有任何源码,只有一个pom文件,它的作用就是帮我们引入其它jar。

2.配置数据源

spring:
 datasource:
    type:com.zaxxer.hikari.HikariDataSource
    url:jdbc:mysql://127.0.0.1:3306/mybatis_test
    username:root
    password:root
    driver-class-name:com.mysql.jdbc.Driver
    hikari:
     # 最小空闲连接数量
     minimum-idle:5
     # 连接池最大连接数,默认是10
     maximum-pool-size:60
     # 此属性控制从池返回的连接的默认自动提交行为,默认值:true
     auto-commit:true
     # 一个连接idle状态的最大时长(毫秒),超时则被释放(retired),缺省:10分钟
     idle-timeout:600000
     # 此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认1800000即30分钟
     max-lifetime:1800000
     # 数据库连接超时时间,默认30秒,即30000
     connection-timeout:60000

stater机制帮我们完成了项目起步所需要的的相关jar包。那问题又来了,传统的spring应用中不是要在application.xml中配置很多bean的吗,比如dataSource的配置,transactionManager的配置 ... springboot是如何帮我们完成这些bean的配置的?下面我们来分析这个过程

三、自动配置

1.基于java代码的bean配置

以mybatis为例,在上面的截图中,我们发现mybatis-spring-boot-starter这个包帮我们引入了mybatis-spring-boot-autoconfigure这个包,如下图:

 

 

里面有MybatisAutoConfiguration这个类,打开这个类看看有些什么东西。

 

 

熟悉@Configuration&、@Bean这两个bean的同学或许已经知道了。这两个注解一起使用就可以创建一个基于java代码的配置类,可以用来替代相应的xml配置文件。@Configuration注解的类可以看作是能生产让Spring IoC容器管理的Bean实例的工厂。@Bean注解告诉Spring,一个带有@Bean的注解方法将返回一个对象,该对象应该被注册到spring容器中。所以上面的MybatisAutoConfiguration这个类,自动帮我们生成了SqlSessionFactory这些Mybatis的重要实例并交给spring容器管理,从而完成bean的自动注册。

2.自动配置条件依赖

从MybatisAutoConfiguration这个类中使用的注解可以看出,要完成自动配置是有依赖条件的。

@org.springframework.context.annotation.Configuration
@ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class })
@ConditionalOnBean(DataSource.class)
@EnableConfigurationProperties(MybatisProperties.class)
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
publicclass MybatisAutoConfiguration {

 privatestaticfinal Logger logger = LoggerFactory.getLogger(MybatisAutoConfiguration.class);

 privatefinal MybatisProperties properties;

 privatefinal Interceptor[] interceptors;

 privatefinal ResourceLoader resourceLoader;

 privatefinal DatabaseIdProvider databaseIdProvider;

 privatefinal List<ConfigurationCustomizer> configurationCustomizers;
 ......

首先预习一下Springboot是常用的条件依赖注解有:

@ConditionalOnBean,仅在当前上下文中存在某个bean时,才会实例化这个Bean。

@ConditionalOnClass,某个class位于类路径上,才会实例化这个Bean。

@ConditionalOnExpression,当表达式为true的时候,才会实例化这个Bean。

@ConditionalOnMissingBean,仅在当前上下文中不存在某个bean时,才会实例化这个Bean。

@ConditionalOnMissingClass,某个class在类路径上不存在的时候,才会实例化这个Bean。

@ConditionalOnNotWebApplication,不是web应用时才会实例化这个Bean。

@AutoConfigureAfter,在某个bean完成自动配置后实例化这个bean。

@AutoConfigureBefore,在某个bean完成自动配置前实例化这个bean。

所以要完成Mybatis的自动配置,需要在类路径中存在SqlSessionFactory.class、SqlSessionFactoryBean.class这两个类,需要存在DataSource这个bean且这个bean完成自动注册。进入DataSourceAutoConfiguration这个类,可以看到这个类属于这个包:org.springframework.boot.autoconfigure.jdbc 这个包又属于spring-boot-autoconfigure-2.0.4.RELEASE.jar这个包,自动配置这个包帮们引入了jdbc、kafka、logging、mail、mongo等包。很多包需要我们引入相应jar后自动配置才生效。

 

 

3.Bean参数的获取

到此我们已经知道了bean的配置过程,但是还没有看到springboot是如何读取yml或者properites配置文件的的属性来创建数据源的?在DataSourceAutoConfiguration类里面,我们注意到使用了EnableConfigurationProperties这个注解。

@Configuration
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({ DataSourcePoolMetadataProvidersConfiguration.class,
		DataSourceInitializationConfiguration.class })
publicclass DataSourceAutoConfiguration {

	@Configuration
	@Conditional(EmbeddedDatabaseCondition.class)
	@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
	@Import(EmbeddedDataSourceConfiguration.class)
	protectedstaticclass EmbeddedDatabaseConfiguration {

	}
......

DataSourceProperties中封装了数据源的各个属性,且使用了注解ConfigurationProperties指定了配置文件的前缀。

@ConfigurationProperties(prefix = "spring.datasource")
publicclass DataSourceProperties implements BeanClassLoaderAware, InitializingBean {

	private ClassLoader classLoader;

	/**
	 * Name of the datasource. Default to "testdb" when using an embedded database.
	 */
	private String name;

	/**
	 * Whether to generate a random datasource name.
	 */
	privateboolean generateUniqueName;

	/**
	 * Fully qualified name of the connection pool implementation to use. By default, it
	 * is auto-detected from the classpath.
	 */
	private Class<? extends DataSource> type;

	/**
	 * Fully qualified name of the JDBC driver. Auto-detected based on the URL by default.
	 */
	private String driverClassName;

	/**
	 * JDBC URL of the database.
	 */
	private String url;

	/**
	 * Login username of the database.
	 */
	private String username;

	/**
	 * Login password of the database.
	 */
	private String password;

	/**
	 * JNDI location of the datasource. Class, url, username & password are ignored when
	 * set.
	 */
	private String jndiName;

	/**
	 * Initialize the datasource with available DDL and DML scripts.
	 */
	private DataSourceInitializationMode initializationMode = DataSourceInitializationMode.EMBEDDED;

	/**
	 * Platform to use in the DDL or DML scripts (such as schema-${platform}.sql or
	 * data-${platform}.sql).
	 */
	private String platform = "all";

	/**
	 * Schema (DDL) script resource references.
	 */
	private List<String> schema;

	/**
	 * Username of the database to execute DDL scripts (if different).
	 */
	private String schemaUsername;

	/**
	 * Password of the database to execute DDL scripts (if different).
	 */
	private String schemaPassword;

	/**
	 * Data (DML) script resource references.
	 */
	private List<String> data;

	......

通过以上分析,我们可以得知:@ConfigurationProperties注解的作用是把yml或者properties配置文件转化为bean。@EnableConfigurationProperties注解的作用是使@ConfigurationProperties注解生效。如果只配置@ConfigurationProperties注解,在spring容器中是获取不到yml或者properties配置文件转化的bean的。

通过这种方式,把yml或者properties配置参数转化为bean,这些bean又是如何被发现与加载的?

3.Bean的发现

springboot默认扫描启动类所在的包下的主类与子类的所有组件,但并没有包括依赖包的中的类,那么依赖包中的bean是如何被发现和加载的?

我们通常在启动类中加@SpringBootApplication这个注解,点进去看

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
		@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public@interface SpringBootApplication {

	/**
	 * Exclude specific auto-configuration classes such that they will never be applied.
	 * @return the classes to exclude
	 */
	@AliasFor(annotation = EnableAutoConfiguration.class)
	Class<?>[] exclude() default {};

	/**
	 * Exclude specific auto-configuration class names such that they will never be
	 * applied.
	 * @return the class names to exclude
	 * @since 1.3.0
	 */
	 ......

实际上重要的只有三个Annotation:

@Configuration(@SpringBootConfiguration里面还是应用了@Configuration)

@EnableAutoConfiguration

@ComponentScan

@Configuration的作用上面我们已经知道了,被注解的类将成为一个bean配置类。@ComponentScan的作用就是自动扫描并加载符合条件的组件,比如@Component和@Repository等,最终将这些bean定义加载到spring容器中。

@EnableAutoConfiguration 这个注解的功能很重要,借助@Import的支持,收集和注册依赖包中相关的bean定义。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public@interface EnableAutoConfiguration {

	String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

	/**
	 * Exclude specific auto-configuration classes such that they will never be applied.
	 * @return the classes to exclude
	 */
	Class<?>[] exclude() default {};

	/**
	 * Exclude specific auto-configuration class names such that they will never be
	 * applied.
	 * @return the class names to exclude
	 * @since 1.3.0
	 */
	String[] excludeName() default {};

}


如上源码,@EnableAutoConfiguration注解引入了@AutoConfigurationPackage和@Import这两个注解。@AutoConfigurationPackage的作用就是自动配置的包,@Import导入需要自动配置的组件。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public@interface AutoConfigurationPackage {

}


/**
 * {@link ImportBeanDefinitionRegistrar} to store the base package from the importing
 * configuration.
 */
staticclass Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {

	@Override
	public void registerBeanDefinitions(AnnotationMetadata metadata,
			BeanDefinitionRegistry registry) {
		register(registry, new PackageImport(metadata).getPackageName());
	}

	@Override
	public Set<Object> determineImports(AnnotationMetadata metadata) {
		return Collections.singleton(new PackageImport(metadata));
	}

}

new AutoConfigurationPackages.PackageImport(metadata)).getPackageName()

new AutoConfigurationPackages.PackageImport(metadata)

这两句代码的作用就是加载启动类所在的包下的主类与子类的所有组件注册到spring容器,这就是前文所说的springboot默认扫描启动类所在的包下的主类与子类的所有组件。

那问题又来了,要搜集并注册到spring容器的那些beans来自哪里?

进入 AutoConfigurationImportSelector类,

我们可以发现SpringFactoriesLoader.loadFactoryNames方法调用loadSpringFactories方法从所有的jar包中读取META-INF/spring.factories文件信息。

下面是spring-boot-autoconfigure这个jar中spring.factories文件部分内容,其中有一个key为org.springframework.boot.autoconfigure.EnableAutoConfiguration的值定义了需要自动配置的bean,通过读取这个配置获取一组@Configuration类。

org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\
org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener

# Auto Configuration Import Filters
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
org.springframework.boot.autoconfigure.condition.OnClassCondition

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\

每个xxxAutoConfiguration都是一个基于java的bean配置类。实际上,这些xxxAutoConfiguratio不是所有都会被加载,会根据xxxAutoConfiguration上的@ConditionalOnClass等条件判断是否加载;通过反射机制将spring.factories中@Configuration类实例化为对应的java实列。

到此我们已经知道怎么发现要自动配置的bean了,最后一步就是怎么样将这些bean加载到spring容器。

4.Bean 加载

如果要让一个普通类交给Spring容器管理,通常有以下方法:

1、使用 @Configuration与@Bean 注解

2、使用@Controller @Service @Repository @Component 注解标注该类,然后启用@ComponentScan自动扫描

3、使用@Import 方法

springboot中使用了@Import 方法 @EnableAutoConfiguration注解中使用了@Import({AutoConfigurationImportSelector.class})注解,AutoConfigurationImportSelector实现了DeferredImportSelector接口, DeferredImportSelector接口继承了ImportSelector接口,ImportSelector接口只有一个selectImports方法。

selectImports方法返回一组bean,@EnableAutoConfiguration注解借助@Import注解将这组bean注入到spring容器中,springboot正式通过这种机制来完成bean的注入的。

四、总结

我们可以将自动配置的关键几步以及相应的注解总结如下:

1、@Configuration&与@Bean------>>>基于java代码的bean配置

2、@Conditional-------->>>>>>设置自动配置条件依赖

3、@EnableConfigurationProperties与@ConfigurationProperties->读取配置文件转换为bean。

4、@EnableAutoConfiguration、@AutoConfigurationPackage 与@Import->实现bean发现与加载。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

入理解 SpringBoot 启动机制(starter 机制) 的相关文章

  • 关于ConstraintLayout自适应高度遇到的坑

    关于ConstraintLayout自适应高度遇到的坑 记录下来 android layout height 61 34 wrap content 34 为了缩减嵌套层及采用了ConstraintLayout作为dialog布局 但是发现d
  • FluentValidation使用示例

    FluentValidation 是一个 NET 平台下的验证库 xff0c 用于验证对象的属性是否符合预期的规则 它提供了一种简洁的方式来编写验证规则 xff0c 支持链式编程 xff0c 可以轻松地构建复杂的验证逻辑 在 NET 6 中
  • SQLServer创建索引的5种方法

    前期准备 xff1a span class hljs operator span class hljs keyword create span span class hljs keyword table span Employee ID s
  • 正则表达式(匹配第一个花括号)

    学习正则 xff0c 工作中使用正则让我对 有了新的认知 xff1a 正则中 匹配输入字符串的开始位置 xff0c 除非在 方括号表达式中使用 xff0c 此时表示不接受该字符集合 废话不多说 xff0c 直接看栗子吧 xff0c 如下图所
  • windows驱动注册中断服务程序

    一个驱动程序的标准中断服务例程的必要功能和建立一个ISR的需求 1 1 ISR需求 一个产生中断的物理设备的所有驱动程序必须有一个ISR 中断服务例程由内核定义如下 xff1a span class hljs built in BOOLEA
  • Android Studio 出现“Cannot resolve symbol” 解决办法

    一 Android Studio 无法识别同一个 package 里的其他类 xff0c 将其显示为红色 xff0c 但是 compile 没有问题 鼠标放上去后显示 Cannot resolve symbol XXX xff0c 重启 A
  • input[type=file] 获取上传文件的内容

    上代码 xff1a span class token tag span class token tag span class token punctuation lt span input span span class token att
  • 解决pyinstaller打包后C盘出现 windows/TEMP/_MEI文件夹爆满的问题

    背景 xff1a 一每分钟执行的python脚本 xff0c 打包成exe后 xff0c 在有些机器出现 IME文件过多的问题 解决 xff1a 1 参考 Python转exe方法与 MEI清除方法 Don 39 t expect me t
  • 关于Android studio 升级到4.2文件缺失问题

    一 背景 当我把Android studio 开开心心的更新到4 2版本后 xff0c 结果就爆了一个类文件找不到的异常 xff08 如下图 xff0c 幸好只有一个 关于这个类的缺失是高版本JRE中剔除了这个类 xff0c 那只要把And
  • 求正整数n所有可能的和式的组合

    求正整数n所有可能的和式的组合 xff08 如 xff1b 4 61 1 43 1 43 1 43 1 1 43 1 43 2 1 43 3 2 43 1 43 1 2 43 2 xff09 首先说一下 xff0c 群里面很多人在问这个东东
  • Error:FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':app:t

    今日份遇到的 bug xff1a Error 注 某些输入文件使用或覆盖了已过时的 API 注 有关详细信息 请使用 Xlint deprecation 重新编译 注 某些输入文件使用了未经检查或不安全的操作 注 有关详细信息 请使用 Xl
  • JVM调优-解决native heap持续增长

    问题的提出 xff0c 分析 xff0c 请参考JNI 小心 xff0c 内存怪兽出没 xff08 简单的说起来 xff0c 就是java进程占用了4G内存 xff0c 但是折腾来折腾去 xff0c 整个JVM的堆才100M上下 xff0c
  • Centos 7 安装openjdk8 /jdk8/jre8 mvn-3.5.2 其他版本雷同

    文章目录 openjdk8jdk8 jre8maven 3 5 2源码下载指导 openjdk8 一 使用yum命令搜索支持jdk版本 yum search java grep jdk 二 使用yum安装jdk8 yum install y
  • 【2023最新版】Hexo+github搭建个人博客并绑定个人域名

    Hexo 43 github搭建个人博客并绑定个人域名 本篇教程完整讲述了如何利用Hexo 43 github搭建个人博客并且绑定自己的域名 xff0c 成为自己的网站 xff01 我的博客网站 xff1a 武师叔 做一个有趣而不甘平庸的人
  • H13-531云计算HCIE V2.0——1~400常错题和知识点总结

    1 100 35 FusionStorage Block无法是被配置RAID的磁盘 一定要将RAID信息删除后 Fusionstrage block才能识别到这些磁盘 错误 61 Ceilometer监控通过在计算节点部署Compute服务
  • 我的2013

    今天是2013年的最后一天 xff0c 天气格外的晴朗 xff0c 站在公司的写字楼上 xff0c 能够看到远处的山水 一直都习惯在一年的最后总结一下 xff0c 总结自己哪些地方在成长 xff0c 哪些地方有收获 xff0c 哪些地方需要
  • 项目管理中的TR点

    TR的意思是技术评审 xff0c 是英语Technical Review的简写 一般项目管理中有以下一些技术评审点需要关注 xff1a TR1 概念阶段技术评审点 xff1a 产品需求和概念技术评审 xff08 业务需求评审 xff09 T
  • linux ln 命令使用参数详解(ln -s 软链接)

    这是linux中一个非常重要命令 xff0c 请大家一定要熟悉 它的功能是为某一个文件在另外一个位置建立一个同不的链接 xff0c 这个命令最常用的参数是 s 具体用法是 xff1a ln s 源文件 目标文件 当 我们需要在不同的目录 x
  • 别再让C++头文件中出现“using namespace xxx;”

    在这里 xff0c 我毫不回避地说了这句话 xff1a 引用 我再也不想在任何头文件中看到 using namespace xxx 了 作为一个开发者 团队领导者 xff0c 我经常会去招聘新的项目成员 xff0c 有时候也帮助其他组的人来
  • Linux 查看监听端口的方法

    61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61

随机推荐

  • SVN MERGE 和冲突

    摘要 xff1a 最佳做法是避免冲突 冲突时 xff0c 不要把branch merge到trunk 先由最新版本的trunk得到branch 然后再修改文件 xff0c 直接merge过去就行 这样不会有冲突 先用svn merge dr
  • Linux命令之basename使用

    basename 命令 首先使用 help 参数查看一下 basename命令参数很少 xff0c 很容易掌握 basename help 用法示例 xff1a basename usr bin sort 输出 34 sort 34
  • android log详解

    之前两篇文章之后 xff0c 打算再分享一点儿经验 xff1a 之前文章见这里 xff1a 1 xff0c 全看懂了 加两年经验 语音朗读 语音识别 语音控制软件源码 2 xff0c 学生作品 配置NDK集成开发环境全过程第一版 这次打算通
  • 各种编码知识简介

    本文主要介绍我们在日常开发中接触到了latin1 xff0c GBK xff0c GB18030 xff0c UTF 8 编码几种 下面首先来看看这几种编码的的区别 latin1 1 先来看看latin1 参考百度百科 Latin1 是IS
  • Linux 技巧:让进程在后台可靠运行的几种方法

    我们经常会碰到这样的问题 xff0c 用 telnet ssh 登录了远程的 Linux 服务器 xff0c 运行了一些耗时较长的任务 xff0c 结果却由于网络的不稳定导致任务中途失败 如何让命令提交后不受本地关闭终端窗口 网络断开连接的
  • nohup命令浅析

    要将一个命令放到后台执行 xff0c 我们一般使用nohup sh command amp amp 都知道是放到后台执行这个命令 xff0c 那么nohup是做什么的 xff1f 这就要从unix的信号说起 xff0c unix的信号机制可
  • 《曾国藩家书大全集》读书笔记——励志篇

    曾国藩将立志作为人生第一要义 xff0c 只要能立志 xff0c 便人人都可以做圣贤豪杰 人生不但要立志 xff0c 还要持之以恒 xff0c 持之以恒是人生第一美德 xff0c 人而无恒 xff0c 将一事无成 曾国藩很重视逆境对人心志的
  • 书,永远的朋友

    我自己认为我是一个不大喜欢看书的人 xff0c 相对于书 xff0c 我可能跟喜欢看视频和同高手一起讨论交流 但是 xff0c 真正静下心来 xff0c 想着这么多年来 xff0c 对我影响很大的一些书 xff0c 也能想到一些 索性 xf
  • PackageManagerService Android 8.1 源码解读 01

    一 PackageManagerService 是什么 xff1f 答 PackageManagerService xff08 简称 PKMS xff09 xff0c 是 Android 系统中核心服务之一 xff0c 负责应用程序的安装
  • IMU之磁力计校准&地磁场&计算磁航向

    背景知识 xff1a 导航坐标系 xff1a 东 北 天 载体坐标系 xff1a 右 前 上 欧拉角定义 xff1a 3 1 2旋转 xff0c xff08 航向角 俯仰角 滚转角 xff09 xff1b 航向角北偏西为正 xff0c 范围
  • 机器学习库scikit-learn简介(一)

    一 机器学习问题 通常 xff0c 学习问题考虑n个样本数据集 xff0c 然后预测未知数据的属性 若各个样本多于一个 xff0c 例如 xff0c 对于多维的条目 xff08 又称多元数据 xff09 xff0c 即说有多个属性或特性 我
  • 前台解析jwt token 前后端分离 ant design pro

    前言 在如今得环境下 xff0c 越来越多得项目采用微服务 xff0c 前后端分离项目 优点在于同时开发 xff0c 分开部署 缺点在于需要约定的太多 xff0c 导致前后端联调产生分歧 就标题而言 xff0c 解决前端antd 接收后台返
  • win10 双击启动nacos报错 Unable to start web server...... Unable to start embedded Tomcat

    1 遇到的问题 win10双击启动nacos报错 2 分析 从启动cmd开始查看 发现 启动模式为集群模式 定位成功 3 解决 修改startup中启动模式 重新启动 成功
  • 【进程间通信】——认识同步与互斥,了解生产者消费者原理。

    临界资源 在操作系统中 xff0c 进程是占有资源的最小单位 xff08 线程可以访问其所在进程内的所有资源 xff0c 但线程本身并不占有资源或仅仅占有一点必须资源 xff09 但对于某些资源来说 xff0c 其在同一时间只能被一个进程所
  • IDEA 远程debugger SpringBoot项目 超赞!!!

    如题哦 xff0c 项目发布到服务器上后 xff0c 每天被不同的bug所困扰 强大的idea超出你的想象 xff0c 强大到可以远程debugger xff0c 就和在本地一样一样的 进入正题 前提概要 线上即服务器代码必须与本地一致 x
  • git提交时 # Please enter the commit message for your changes. Lines starting # with ‘#‘ will be ignored

    问题 xff1a Please enter the commit message for your changes Lines starting with 39 39 will be ignored and an empty message
  • canal 修改配置信息后监听不到mysql数据并报错can‘t find start position for example

    原由 xff1a 数据库地址变化 canal 需要修改监听 问题 xff1a 修改配置信息后重启canal 但并无监听到数据库信息变化 分析 xff1a canal 与数据库之间断层 xff0c 导致信息传输失败 解决 xff1a xff0
  • win7 配置JDK环境变量

    第一步 xff1a 安装jdk 8u101 windows x64 exe xff0c 路径为默认路径 xff0c 一直下一步直到完成安装 安装最好不要修改安装路径 xff0c 防止自己找不到 第二步 xff1a 设置环境变量 xff1a
  • 完整的搭建内网穿透ngrok详细教程(有图有真相)

    如上 网上找到的都是不稳定的 还不如自己搭建一个 去问度娘了 xff0c 发现了一堆 好吧 xff0c 那就动手开干吧 准备工作 xff08 其实也是硬性条件 xff09 xff1a 1 服务器一台 2 备案域名一个 xff08 好多都说可
  • 入理解 SpringBoot 启动机制(starter 机制)

    深入理解 SpringBoot 启动机制 xff08 starter 机制 xff09 一 前言二 起步依赖三 自动配置 1 基于java代码的bean配置2 自动配置条件依赖3 Bean参数的获取3 Bean的发现4 Bean 加载四 总