【微服务专题】SpringBoot自动配置源码解析

目录

  • 前言
  • 阅读对象
  • 阅读导航
  • 前置知识
  • 笔记正文
    • 0、什么是自动配置
      • 0.1 基本概念
      • 0.2 SpringBoot中的【约定大于配置】
      • 0.3 从SpringMVC看【约定大于配置】
      • 0.4 从Redis看【约定大于配置】
    • 一、@EnableAutoConfiguration源码解析
    • 二、SpringBoot常用条件注解源码解析
      • 2.1 自定义条件注解
      • 2.2 @ConditionalOnClass原理解析
      • 2.3 ConditionalOnBean原理解析
    • 三、SpringBoot之Mybatis自动配置源码解析
    • 四、SpringBoot之AOP自动配置源码解析
    • 五、SpringBoot Jar包启动过程源码解析
  • 学习总结
  • 感谢

前言

想要搞懂自动装配,需要当前系列前两篇笔记内容打底。不过我上一篇笔记写的不好,没有什么突出的重点,主要也是当时跟着课程看了源码之后,也没发现什么特别的,直到在看自动装配源码的时候,才后知后觉遗漏了一些重要的知识点。但是总体来说不影响这一节课的笔记记录吧。

阅读对象

阅读导航

系列上一篇文章:《【微服务专题】Spring启动过程源码解析》

前置知识

笔记正文

0、什么是自动配置

我们说起SpringBoot,总会不自觉的联想到自动配置约定大于配置等标签,但说实在,我是有一点困惑的,这个【约定和配置】到底是什么意思,或者说,它们具体指的是哪些内容啊?!
我在想,像我这种,只是用过那么一年多SSM/SSH,甚至完全没有经历过的人来说,是很难理解的。虽然我也确实经历过SSM/SSH,但那时候初出茅庐,根本就没在意过这些玩意好吧…

不过话说回来,后面再回来继续做Java的时候,已经是SpringBoot的时代了嘛,所以单从片面印象来说的话:SpringBoot确实方便了很多。最最最直观的就是启动,给我的感觉启动一个web应用跟简单运行了一个main方法一样便捷。而在以前SSM/SSH时代,各种眼花缭乱的xml配置,还有那个令人烦躁的tomcat配置,就已经让我很难受了。

好吧,不懂嘛,于是我就去稍微学习了一下。下面,我就按照我自己的理解,再拼上一些百度的、起码能说服我自己的答案给大家说道说道。另外,也想举一个真正直观的例子给大家说说,【约定和配置】到底使了什么魔法

0.1 基本概念

【约定大于配置】是一种开发思想、设计理念,它强调使用默认约定和规则,减少开发者需要做的【显式】配置。根据这一原则,大部分情况下,开发者只需关注那些【不符合默认约定】的配置,而不需要为每个细节都进行显式配置。

开天眼给大家说一下:既然结果是减少了需要程序员【显示】配置的工作量,那反过来就证明了,在SpringBoot之前的时代,有一些配置是不得不(必须)需要程序员去配置的!
另外,这里说的【配置】,不是指xml配置,而是对引入的服务的所有形式的配置,xml只是一种介质而已,我们还可以是txtyml,还有java文件的配置方式。
我认为这个结论很重要!我后面研究案例就是往这方向去看的

综上所述,可以这样简单地理解【约定】和【配置】:

  1. 默认规则
  2. 【显示】配置(不得不设置的配置 / 没办法使用默认规则的配置)。这里说的【配置】,不是指具体的xml配置,而是对引入的服务的【所有形式】的配置,xml只是其中一种形式而已,配置还可以是txtyml,包括java文件的配置形式。

这个理念,有如下显著的优势:

  1. 提高开发效率: 通过遵循默认约定,开发者可以快速启动项目并进行开发,无需花费大量时间在繁琐的配置上
  2. 减少决策负担: 【约定大于配置】减少了开发者需要做出的决策,使开发过程更加流畅,不需要在每个细节上做出选择
  3. 减少错误: 默认约定可以减少配置错误的机会,因为开发者只需要在特定情况下进行配置,从而降低了出错的可能性

0.2 SpringBoot中的【约定大于配置】

我们都知道,SpringBoot是基于Spring的,严格来说,SpringBoot的出现其实是为了降低Spring的使用门槛。

  1. 使用maven的目录结构。默认有src-main-resources文件夹,存放资源配置文件;src-main-java存放项目java源码;target文件夹存放编译、打包内容(其实,Maven的设计本身就是遵循【约定大于配置】的原则)

这是约定的一种,通过约定这些内容,使得项目结构统一,减少了开发人员学习成本。
试想一下,如果我们在不同的公司,他们的项目结构五花八门,甚至没有src/main/resources,没有src/main/java等目录,你学习成本是不是变高了??博主之前写过2、3年C/C++,那时候接触的项目就是这个鸟样子的,都是自定义资源存放目录,打包目录,源码目录,真的吐血… … 我转战Java很大一个原因就是奔着Java的规范性去的。当然,我现在相当后悔…

  1. 使用application.properties/yml文件设置配置内容

这也是一种约定,拒绝程序员五花八门的配置文件

  1. 默认使用Tomcat容器

接触过SSM吗?SSM项目通常来说,需要额外配置启动一个Tomcat,然后将SSM项目打包部署到Tomcat上
而在SpringBoot中,我们启动项目就跟运行一个普通的main函数一样

  1. 提供了大量的自动配置接口,自动配置类,注解等,帮助程序员配置。严格来说,自动配置接口以及注解等,都是为了自动配置类服务的。SpringBoot提供的大量自动配置类,在里面默认设置了很多值用以配置第三方接口服务,这些默认配置甚至能让开发做到开箱即用,只有一些不得不需要用户设置的内容才需要开发人员自己设置。这就是上面概念所谓的开发者只需要关注那些不符合默认约定的配置的意义。

这是SpringBoot【约定大于配置】的重要实现。我们先稍微解释一下,这些所谓的接口、类、注解是指什么:

  • 自动配置接口:AutoConfigurationImportFilter、AutoConfigurationImportListener等
  • 自动配置类:DispatcherServletAutoConfiguration、HttpEncodingAutoConfiguration等
  • 注解:诸如@AutoConfiguration、@AutoConfigurationPackage等

    上述我只是简单列举了一些内容而已,其实具体的,可以看:org.springframework.boot:spring-boot-autoconfigure这个包。里面就是SpringBoot为大家做自动配置提供的默认配置,和相关接口

0.3 从SpringMVC看【约定大于配置】

说实在,SpringMVC我不是很熟悉,所以我不是很保证自己说的是对的,在网上也没看到非常令人信服的答案。但是关于【约定大于配置】的体现我觉得还是正确的。

有人说spring-boot-starter-web其实就是面配置的SSM。在SSM时代,我们想要开发一个web应用,免不了如下配置:

  1. 新增web.xml,在里面配置前端控制器DispatcherServlet、视图解析器ViewResolver、过滤器等
  2. 新增核心配置文件**-servlet.xml
  3. Tomcat容器的配置
  4. 等等…

其实说需要新增这种那种xml配置是有点狭隘的说法,我前面说过了xml只是其中一种配置形式而已。
准确来说,传统的SSM项目,需要我们开发人员显式、准确地向Spring容器注册DispatcherServletViewResolverSqlSessionFactoryBeanDriverManagerDataSource
如果我们没有【显式】地去声明、注册这些Bean,那我们项目直接启动失败!他会说找不到这个找不到那个。但是,在SpringBoot中,我们只需要在pom中引入spring-boot-starter-web就可以了,这个jar包,会自动向Spring中注册上述关键bean

怎么注册?我们简单看一下关于SpringMVC的自动配置类。

1)WebMvcAutoConfiguration.java:SpringMVC的自动配置入口
在这里插入图片描述
在这里我们无需关心上面的诸多注解的具体含义先,具体意义我会在后面的源码解析中介绍。
但是可以预见的是,在某种情况下,spring-boot-stater-web会进入DispatcherServletAutoConfiguration.class里面

2)DispatcherServletAutoConfiguration.java:在这里,有一个@Bean,暂不关心他什么时候会被触发,但至少可以预见的是:在某种情况下,DispatcherServletAutoConfiguration类会向Spring中注册一个DispatcherServlet类型的bean
在这里插入图片描述
啊,对的,本质上就是如此而已。SpringBoot的自动配置,实际上就是SpringBoot的源码中预先写好了一些配置类,预先定义好了一些Bean,我们在用SpringBoot时,这些配置类就已经在我们项目的依赖中了,而这些自动配置类或自动配置Bean到底生不生效,就看具体所指定的条件了。

不过还有一点需要说明,那就是SpringBoot可不是简简单单的给你注册了一个默认的bean,它还会给部分【符合约定】的基础参数设置默认的、至少有意义的、比较符合一般应用的初始值来初始化bean。这个就是SpringBoot提供的各种XxxProperties.java。例如:WebMvcProperties
在这里插入图片描述
O对了,说到了这个XxxProperties.java文件,其实它也是约定的一种体现。以前SSM我们相当于直接配置了服务接口的一些参数;而在SpringBoot里面,我们直接配置的其实是XxxProperties,然后再由SpringBoot使用XxxProperties配置属性去初始化服务接口参数。而通常这些XxxProperties对应的是application.properties里面的一些配置内容。
相比起直接配置服务接口参数,XxxProperties可读性更强,使用也更简单。

0.4 从Redis看【约定大于配置】

省略

OK,关于SpringBoot中的【约定大于配置】就介绍到这里了。那他们是怎么实现的呢?有经验的朋友,或者稍微细心的朋友估计也从上图看到了,主要是靠下图这些类、接口、注解:org.springframework.boot:spring-boot-autoconfigure包下
在这里插入图片描述

一、@EnableAutoConfiguration源码解析

二、SpringBoot常用条件注解源码解析

SpringBoot中的常用条件注解有:

  • ConditionalOnBean:是否存在某个某类或某个名字的Bean
  • ConditionalOnMissingBean:是否缺失某个某类或某个名字的Bean
  • ConditionalOnSingleCandidate:是否符合指定类型的Bean只有一个
  • ConditionalOnClass:是否存在某个类
  • ConditionalOnMissingClass:是否缺失某个类
  • ConditionalOnExpression:指定的表达式返回的是true还是false
  • ConditionalOnJava:判断Java版本
  • ConditionalOnWebApplication:当前应用是不是一个Web应用
  • ConditionalOnNotWebApplication:当前应用不是一个Web应用
  • ConditionalOnProperty:Environment中是否存在某个属性
  • 当然我们也可以利用@Conditional来自定义条件注解

条件注解是可以写在类上和方法上的,如果某个条件注解写在了自动配置类上,那该自动配置类会不会生效就要看当前条件能不能符合;或者条件注解写在某个@Bean修饰的方法上,那这个Bean生不生效就看当前条件符不符合。

具体原理是:

  1. Spring在解析某个自动配置类时,会先检查该自动配置类上是否有条件注解,如果有,则进一步判断该条件注解所指定的条件当前能不能满足,如果满足了则继续解析该配置类,如果不满足则不进行解析了,也就是配置类所定义的Bean都得不到解析,也就是相当于没有这些Bean了。
  2. 同理,Spring在解析某个@Bean的方法时,也会先判断方法上是否有条件注解,然后进行解析,如果不满足条件,则该Bean不会生效

2.1 自定义条件注解

SpringBoot中众多的条件注解,都是基于Spring中的@Conditional来实现的,我们先来用一下@Conditional注解。
先来看下@Conditional注解的定义:

/*** * 指示组件只有在所有指定条件匹配时才有资格注册。* 条件是可以在注册bean定义之前以编程方式确定的任何状态(有关详细信息,请参阅条件)。* @Conditional注释可以以以下任何一种方式使用:* 在任何直接或间接用@Component注释的类(包括@Configuration类)上作为类型级注释* 作为元注释,用于组合自定义构造型注释* 作为任何@Bean方法上的方法级注释* 如果@Configuration类被标记为@Conditional,那么与该类关联的所有@Bean方法、@Import注释和@ComponentScan注释* 将受这些条件的约束。*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {/*** All {@link Condition} classes that must {@linkplain Condition#matches match}* in order for the component to be registered.*/Class<? extends Condition>[] value();}

根据定义我们在用@Conditional注解时,需要指定一个或多个Condition的实现类,所以我们先来提供一个实现类:

public class ShenCondition implements Condition {@Overridepublic boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {Map<String, Object> component = metadata.getAnnotationAttributes("org.springframework.stereotype.Component");System.out.println("下面开始打印condition里面的内容");System.out.println(component);Object value = component.get("value");return value.toString().equals("shen");}
}

上面这个实现类很简单,就是获取被@Conditional(ShenCondition.class)注解的类上,获取它@Component上的注解值,如果值是shen那就返回true,否则bean注册不成功。测试用例如下:

@Conditional(ShenCondition.class)
@Component("shen")
public class ShenWorker {public String sayHello() {return "hello";}
}@SpringBootApplication(scanBasePackages = "org.example.springboottest")
public class ShenMyApplication {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(ShenMyApplication.class);ShenWorker shen = (ShenWorker) context.getBean(ShenWorker.class);System.out.println("------------------------");System.out.println(shen.sayHello());}
}

此时运行,控制台输出:
在这里插入图片描述
把上面的ShenWorker @Component值改成其他,如@Component("shenWorker"),运行则输出如下:
在这里插入图片描述
报错了,NoSuchBeanDefinitionException
我想到了这里大家应该多少知道@Conditional注解的作用了,接下来我们挑其中一两个SpringBoot声明的条件注解,看一下源码,剖析一下它是怎么实现的。

2.2 @ConditionalOnClass原理解析

@ConditionalOnClass注解的作用是:校验是否存在某个类。

Spring这种优秀源码,通常注释都是很完善的,我们先来看看它们是怎么定义的:

/*** @Conditional,当且仅当指定的类在类路径上时,才匹配成功** value()可以在@Configuration类上安全地指定,因为在加载类之前,* 会使用ASM解析注释元数据。当放置在@Bean方法上时,需要特别注意,* 考虑在单独的Configuration类中隔离条件,特别是如果方法的返回类型与条件的目标匹配*/
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnClassCondition.class)
public @interface ConditionalOnClass {/*** 必须设置的class信息。* 因为这个注释是通过加载类字节码来解析的(classLoader.loadClass),* 当且仅当这个注解直接作用在bean上,而不是当这个注解被用作组合的元注释时,* 在这里指定最终可能不在classpath上的类是安全的(不会报错)。* 想要将此注解用作元注释,那么就只使用name属性*/Class<?>[] value() default {};/*** 必须设置的类全限定名*/String[] name() default {};
}

根据我们自定义注解经验,该注解的实现肯定是在@Conditional(OnClassCondition.class)OnClassCondition.class中。
顺便在这里介绍一下怎么用idea追踪代码吧。

1)寻找关键实现类
首先我们知道,OnClassCondition.class实现自Condition接口,主要是实现里面的matches()方法。虽然咱还不知道它是在哪里被Spring调用的,但起码他肯定是会被调用的对吧,所以,我们先跳到OnClassCondition.class文件,打开它的继承图,如下所示:
在这里插入图片描述
可以发现它继承或者实现了各种各样的接口,其中一个是Condition。那OK
我们在回到OnClassCondition.class文件,alft+7打开代码结构图,然后在右上角点击查看继承过来的属性、方法,如下所示:
在这里插入图片描述
如上图所示,绿色框内灰色的即为继承过来,但是没有重写的方法。可以看到Condition接口的matches方法,就没有被重写过,那说明父类中肯定有默认的实现类,点击一下,会跳到SpringBootCondition类中,它的默认实现方式如下:
在这里插入图片描述
可以看到,最重要的是红框内的2行代码。点击getMatchOutcome发现这是一个抽象方法,所以,又回到OnClassCondition.class文件中,查找一下看看是否实现或者重写了该方法。最后发现如下:
在这里插入图片描述
重写了,再结合之前的代码可以判断出来,这里就是OnClassCondition类的逻辑实现核心。上面的代码其实也不难,基本上通过方法名就知道啥意思了。主要原理就是:使用反射工具,根据权限定名去JVM加载类。

特别注意:@ConditionalOnClass和@ConditionalOnMissingClass注解的核心实现都是这个类的这个方法

2.3 ConditionalOnBean原理解析

点击查看@ConditionalOnBean注解,会发现逻辑是在OnBeanCondition.class中,然后按照上面的思路也会发现,它跟前面的注解基本一致,实现逻辑也是在getMatchOutcome中,如下:
在这里插入图片描述
这个源码略显复杂,但是可以通过阅读注解接口的各种字段信息,推断出来具体过程。总的来说就是根据bean是否存在来返回结果。

特别注意:@ConditionalOnBean和@ConditionalOnSingleCandidate,@ConditionalOnMissingBean注解的核心实现都是这个类的这个方法

三、SpringBoot之Mybatis自动配置源码解析

在我们的项目pom中,导入如下:

 <dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId></dependency>

我们就会看到我们项目依赖中出现以groupId+artifactId命名的jar包了,如下:
在这里插入图片描述
对的,通常第三方在写自动配置的时候,命名风格皆是如此。而在里面的MybatisAutoConfiguration即为Mybatis的自动配置类。通过源码我们可以发现,在里面注册了两个bean,当然是有条件的:
在这里插入图片描述
上面的意思是,在Spring中如果没有SqlSessionFactory这个类型的bean,则注册当前bean;
另一个注册的bean如下:
在这里插入图片描述
最核心的一个还是,在自动配置类下面有一个这玩意:
在这里插入图片描述
这个 Bean的作用是,如果没有其他显式的注册Mapper扫描映射器,那就注册一个默认的Mapper扫描映射器,扫描路径跟SpringBoot扫描路径一致。说到这里,是不是有朋友对Mybatis如何实现把接口转换成bean这个操作感兴趣呢?大家伙可以看看按照下面这个轨迹从1-9-AB,自上而下去看看,但是需要一些Spring功底。源码入口:MybatisAutoConfiguration.AutoConfiguredMapperScannerRegistrar#registerBeanDefinitions(我有一点功底,但不算很扎实)
在这里插入图片描述
总的来说,它的原大致如下:(注意,这里是指默认自动配置类情况下,如果使用了@MapperScan注解,情况略有不同)

  1. Mybatis自动配置类会向Spring容器注册一个扫描器Bean定义,根据Bean定义,初始化扫描器属性。默认扫描路径是当前SpringBoot的扫描路径
  2. Mybatis会修改扫描到Mapper接口的自动注入属性
  3. Mybatis会修改注册成为Bean的条件,原本接口类是不能够被注册成为Bean的,但是通过修改条件让其通过了判断
  4. 具体怎么生成的Bean我还没去看…,睡觉了

四、SpringBoot之AOP自动配置源码解析

未完待续…

五、SpringBoot Jar包启动过程源码解析

未完待续…

学习总结

感谢

感谢阿里云社区的文章《探索Spring Boot中的原则:约定大于配置》
感谢百度大佬【作者:编程师兄】的文章《SpringBoot约定大于配置到底是什么意思?》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/168246.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java 反射和注解1-反射详解

反射和注解本就是一家人&#xff0c;注解离不开反射&#xff0c;这里先将反射的写法&#xff0c;本文涉到的注解暂时可以不不用理解 1&#xff0c;创建一个类 public class ReflexUser {public String name;private String namePrivate;protected String nameProtected;Strin…

Arduino库之 LedControl 库说明文档

LedControl 库最初是为基于 8 位 AVR 处理器的 Arduino 板编写的。用于通过MAX7219芯片控制LED矩阵和7段数码管。但由于该代码不使用处理器的任何复杂的内部功能&#xff0c;因此具有高度可移植性&#xff0c;并且应该在任何支持 和 功能的 Arduino&#xff08;类似&#xff09…

模拟火车订票系统---python序列

if __name__ __main__:#创建车辆信息列表list["车次","出发站-到达站","出发时间","到达时间","历时","余票"]trainNumber[T40,T298,Z158,Z62]address[长春-北京,长春-北京,长春-北京,长春-北京]getTime[00:12,0…

简单介绍一下js中的构造函数、原型对象prototype、对象原型__proto__、原型链

构造函数 function Star (uname, age){this.uname unamethis.age agethis.sing function(){ log(唱歌~) }}let xzq new Star(薛之谦, 30)let ldh new Star(刘德华, 20)log(ldh) // { uname: 刘德华, age: 20, sing: f }ldh.sing() // 唱歌~log(ldh.sing xzq.sing) // fal…

DevEco Studio安装

HUAWEI DevEco Studio For OpenHarmony&#xff08;以下简称DevEco Studio&#xff09;是基于IntelliJ IDEA Community开源版本打造&#xff0c;面向OpenHarmony全场景多设备的一站式集成开发环境&#xff08;IDE&#xff09;&#xff0c;为开发者提供工程模板创建、开发、编译…

服务器被入侵了怎么去排查

在当今数字化时代&#xff0c;网络安全问题变得越来越重要。其中&#xff0c;服务器被入侵是一种常见的安全威胁。当服务器被入侵时&#xff0c;我们需要采取一系列措施来排查和解决问题。本文将为您提供服务器被入侵后的排查步骤。 第一步&#xff1a;确认服务器被入侵 当发现…

C语言进阶之路-基本数据小怪篇

目录 一、学习目标&#xff1a; 二、数据基本类型 整型 浮点型 / 实型 字符 字符串 布尔型数据 三、重要的杂七杂八知识点 常量与变量 标准输入 sizeof运算符&#xff1a; 类型转换 数据类型的本质 整型数据尺寸 可移植性整型 拿下第一个C语言程序 总结 一、学…

web前端之引入svg图片、html引入点svg文件、等比缩放、解决裁剪问题、命名空间、object标签、阿里巴巴尺量图、embed标签、iframe标签

MENU 前言直接在页面编写svg使用img标签引入通过css引入使用object标签引入其他标签参考资料 前言 web应用开发使用svg图片的方式&#xff0c;有如下几种方式 1、直接在页面编写svg 2、使用img标签引入 3、通过css引入 4、使用object标签引入 直接在页面编写svg 在html页面直接…

LeetCode Hot100 101.对称二叉树

题目&#xff1a; 给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 代码&#xff1a; class Solution {public boolean isSymmetric(TreeNode root) {if(rootnull || (root.leftnull && root.rightnull)) {return true;}//用队列保存节点LinkedList<…

【网易云商】构建高效 SaaS 系统的技术要点与最佳实践

SaaS 是什么 定义 相信大家都对云服务中的 IaaS、PaaS、SaaS 早就有所耳闻&#xff0c;现在更是衍生出了 aPaaS、iPaaS、DaaS 等等的类似概念。对于 SaaS 也有各种各样的定义&#xff0c;本文给出的定义是&#xff1a; SaaS 是一种基于互联网提供服务和软件的交付模式&#xf…

水果编曲软件FL Studio21.2下载安装教程

简称FL&#xff0c;全称&#xff1a;Fruity Loops Studio&#xff0c;因此国人习惯叫它"水果"。目前最新版本(包括测试版本)是FL Studio21.2&#xff0c;它让你的计算机就像是全功能的录音室&#xff0c;大混音盘&#xff0c;非常先进的制作工具&#xff0c;让你的音…

工业以太网交换机未来发展中的几个趋势

随着工业自动化不断发展和智能制造的推进&#xff0c;工业以太网交换机在未来的应用中将面临更多的发展机遇和挑战。在工业以太网交换机的未来发展中&#xff0c;有几个方面将成为趋势。 网络虚拟化 随着工业自动化系统规模的不断扩展&#xff0c;网络虚拟化将成为未来的发展方…

四、防火墙-NAT Server

学习防火墙之前&#xff0c;对路由交换应要有一定的认识 NAT Server1.1.基本原理1.2.多出口场景下的NAT Server1.3.源进源出 —————————————————————————————————————————————————— NAT Server 一般对用户提供一些可访问的…

Python开发运维:Django 4.2.7 使用Celery 5.3.5 完成异步和定时任务

目录 一、实验 1.Django使用Celery完成异步和定时任务 二、实验 1. 如何查看Django版本 一、实验 1.Django使用Celery完成异步和定时任务 (1)安装Django (2)新建Django项目 (3)初始框架 (4)urls.py引用视图views from django.contrib import admin from django.urls imp…

CodeWhisperer 体验总结

CodeWhisperer 体验总结 | CodeWhisperer 是一款亚马逊新推出的通用代码生成器 可以实时进行代码数据的提供 还可以定义安全问题 CodeWhisperer 对个人用户是免费使用 企业用户需要订阅使用 亚马逊云科技开发者社区为开发者们提供全球的开发技术资源。这里有技术文档、开发案例…

Linux:配置Ubuntu系统的镜像软件下载地址

一、原理介绍 好处&#xff1a;从国内服务器下载APT软件&#xff0c;速度快。 二、配置 我这里配置的是清华大学的镜像服务器地址 https://mirrors.tuna.tsinghua.edu.cn/ 1、备份文件 sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak2、清空sources.list ec…

广告机/商业显示屏_基于MT8788安卓主板方案

安卓主板在广告机领域扮演着重要的角色。无论是在商场、车站、酒店、电梯、机场还是高铁站&#xff0c;LED广告机广泛应用&#xff0c;并通过不同方式进行播放和管理。 广告机/商业显示屏_基于MT8788安卓主板方案 基于MT8788安卓主板方案的广告机采用了联发科MT8788八核芯片方案…

国标直流充电枪9孔分别啥意思?

DC&#xff1a;直流电源正 DC-&#xff1a;直流电源负 PE&#xff1a;接地&#xff08;搭铁&#xff09;S&#xff1a;通讯CAN-H S-&#xff1a;通讯CAN-L CC1&#xff1a;充电连接确认 CC2&#xff1a;充电连接确认 A&#xff1a;12V A-&#xff1a;12V- 以上就是国标直流充电…

线上ES集群参数配置引起的业务异常案例分析

本文介绍了一次排查Elasticsearch node_concurrent_recoveries 引发的性能问题的过程。 一、故障描述 1.1 故障现象 1. 业务反馈 业务部分读请求抛出请求超时的错误。 2. 故障定位信息获取 故障开始时间 19:30左右开始 故障抛出异常日志 错误日志抛出timeout错误。 故障之前…

BTC 复兴:Ordinals 带来创新活力,BitVM 与 BitStream 相继问世

除了备受瞩目的 ETF&#xff0c;今年 Bitcoin 生态迎来全新的发展活力和机遇。Ordinals 协议的横空出世&#xff0c;以此为基础诞生的 BRC20 协议给整个比特币生态带去了一波新的能量&#xff0c;迎来铭文热度高涨。而诸如 BitVM、BitStream 等新技术甫一问世&#xff0c;便引发…