4.7 深入理解Spring

news2024/11/16 19:51:27

4.7.1 Spring

4.7.1.1 Spring模块

Spring 由七大模块组成,分别是

  • 数据模块(Data Access / Integration
  • Web模块
  • 切面模块(AopAspects
  • 工具模块(Instrumentation)
  • 消息模块
  • 核心模块
  • 测试模块

Spring模块

4.7.1.1.1 数据模块

数据访问与集成模块,分为以下小模块:

  • JDBC (Java Database Connectivity),Java数据库连接
  • ORM (Object Relational Mapping), 对象关系映射
  • OXM (Object XML Mapping), 对象XML映射
  • JMS (Java Message Service),Java消息服务
  • Transactions ,事务

4.7.1.1.2 Web模块

Web有以下小模块:

  • Web
  • WebMVC
  • WebSocket
  • WebFlux

Web 模块:提供了核心部分,如 编解码,过滤器,序列化,国际化,跨域,转换器,客户端和服务端等。

WebMVC 模块:即我们平时用的 SpringMVC

WebSocket 模块: 用来支持这个 全双工通信

WebFlux模块: 就是这个响应式Web编程模块

4.7.1.1.3 切面模块

包括AOP、Aspect两个模块。

AOP:基于代理的 Aop 框架

Aspect:定义了五种类型的切面

  • beans.factory.aspectj
  • cache.aspectj
  • context.annotation.aspectj
  • scheduling.aspectj
  • transaction.aspectj

4.7.1.1.4 工具模块

 Instrumentation , 这个是 Java 的一个接口,用于

  • 监控代理
  • 事件日志记录
  • 代码覆盖率

4.7.1.1.5 消息模块

Spring-messaging 模块提供了一种基于 WebSocket 的 STOMP 协议实现
STOMP (Simple Text Oriented Messaging Protocol) 是一种 流文本定向消息协议,也是一种为MOM(Message Oriented Middleware,面向消息的中间件)设计的简单文本协议
常见的这几个MQ都支持该协议,比如 RocketMQRabbitMQActiveMQ。

待更新

Spring的这七大模块你了解吗? - 知乎

4.7.1.1.6 核心模块

分为四个核心模块:

  • Beans
  • Core
  • Context
  • Expression

该核心模块为重点,

4.7.1.1.7 测试模块

主要是测试用,如Junit等。


4.7.1.2 核心模块 

4.7.2 SpringIOC架构原理

IOC流程图

4.7.2.1 Bean初始化状态

我们可以将bean概念态、定义态、纯静态、成熟态

概念态:

定义态:bean的构造图

纯静态:循环依赖中体现纯静态的作用

成熟态:最终在应用中使用的bean

其中在ApplicationContext()中隐藏了另外两种状态

4.7.2.2 概念bean 定义bean

BeanDefinition是相当重要的 

BeanDefinition:封装了bean的定义信息,决定一个bean是怎么生产的,一个bean对应一个BeanDefinition

那么这个BeanDefinition是怎么来的呢?

当我们new ApplicationContext时会传入一个xml文件。不同的sapring上下文会传入不同的,读取bean定义的过程是有些不同的,但也有相同的地方。

方式一:ClassPathXmlApplicationContext(xml);
方式二:AnnotationConfigApplicationContext(配置类);

无论是ClassPathXmlApplicationContext(xml)还是AnnotationConfigApplicationContext(配置类)都有一个统一的接口ApplicationContext,因此它们会将公共的部分抽取出来,我们来研究这些公共的部分。

虽然有不同的spring上下文,但是都是由BeanDefinitionReader接口读取配置信息

读取之后怎么解析注解呢?

用扫描器ClassPathBeanDefinitionScanner,比如,我们定义了

它会扫描包下的.class,里面有component注解,将这个类注册为BeanDefinition。由于每个类都会有BenaDefinition,所以用beanDefinitionMap容器保存。

之后由registerBeanDefinition将BeanDefinition注册到BeanDefinitionMap中

 之后就是生产bean了。

4.7.2.3 生产bean

 这里涉及到很重要的知识点:BeanFactory接口

BeanFactory负责生产,在BeanFactory中提供了getBean方法用来生产bean。

提出一个小问题,这里Spring容器调用的getBean和BeanFactory里的getBean是同一个方法吗?

答案:是同一个

我们进入applicationContext.getBean(),会发现这里的getBean是门面方法,没有具体,而是交给BeanFactory去生产。

 当已存在bean就直接返回给spring,如果没有就生产后返回。

既然ApplicationContext和BeanFactory都可以获取bean,也就是说二者均可作为容器去使用。

那么既然都可以作为容器,为什么不直接在spring中书写BeanFactroy,非要再整个ApplicationContext的门面方法,不多此一举么?

看完上面的继承图,我们发现ApplicationContext实现了BeanFactroy,这就好比,我们要买车,我们可以选择去4S店,也可以选择直接去汽车工厂。ApplicationContext就好比4S店,4S店有很多的服务,我们只需要提需求,4S店都能完成。BeanFactroy就是汽车工厂,工厂的职责就一个:生产汽车。基本上我们和4S店比较熟悉,打交道比较多,同样我们开发人员和ApplicationContext打交道比较多。我们只需要把配置给ApplicationContext,它就能初始化。

但是BeanFactroy不行,它只实现了简单工厂,功能单一化,只能根据BeanDefinition去生产bean。

通过ApplicationContext,我们只需要getBean(car),就可以得到我们想要的bean,但是,如果注释了ApplicationContext,我们再直接用beanFactory.get(car),就会报错BeanDefinitionException。

因为像xml、配置类的信息,都是由ApplicationContext(Spring 上下文)帮我们做了,ApplicationContext调用了BeanFactory来生产bean。

但是对于BeanFactory,我们必须手动将BenaDefinition传给BeanFactory,才能生产bean。

但是BeanFactory内存更小,可以用于嵌入式开发。

4.7.2.4 实例化bean

实例化bean的方式:

  1. 反射
  2. 工厂方法
  3. 工厂类:FactoryBean

4.7.2.4.1 反射

@Component

将类读取到beanClass中,spring利用反射实例化bean

4.7.2.4.2 工厂方法

注解形式

public class StaticFactoryBean {

   @Bean
    public static UserService createUserService(){    
            return new UserServiceImpl();
    }
}

 会将被标注的方法读取到factoryMethodName

xml形式

而<bean id="" factory-bean="StaticFactoryBean全限定名" factory-method=" UserService"/>

在factory-method=" "中指定一个工厂方法,且这个工厂方法是静态的,会将方法读取到factoryMethodName 

4.7.2.4.3 工厂类

注意FactoryBean本身也是一个bean

 类实例化FactoryBean接口,并重写getObject()、getObjectType()


@Component
public class FactoryBean_test implements FactoryBean {
    @Override
    public Object getObject() throws Exception {
//这个才是返回的真正的bean
        return new User();
    }
 
    @Override
    public Class<?> getObjectType() {
        return User.class;
    }

工厂方法基于方法,而工厂类基于类

4.7.2.5 属性注入

4.7.2.5.1 循环依赖

4.7.2.6 初始化

4.7.2.6.1 初始化方法

属性注入之后,进行初始化,初始化时会调用init_Method()

 除了init-Method()外

还可以用注解@PostConstruct声明一个初始化方法

以及利用InitializingBean接口,实现一个InitializingBean,重写afterPropertiesSet()

4.7.2.6.2 aware扩展接口

检查aware接口设置相关依赖

在spring容器中,我们可以把对象按照使用者分为两类:自定义对象、容器使用的对象

  • 自定义对象:就是我们开发人员定义的Student、Taecher等对象
  • 容器使用的对象:BeanPostProcessor、BeanFactory等,这些都是由容器自己创建、自己调用。

但是如果我们自定义对象需要使用、调用这些容器所使用的对象时,怎么办?

你可以把这些容器所使用的对象当成一个普通属性,如果是属性,我肯定要调用属性的set方法,往里面赋值。但是,对象的创建都交由容器来管理了,set方法调用肯定还是由容器管理,而且容器又不知道什么时候调用。

所以这里设置了统一的入口——aware接口。

所有调用容器对象设置的地方都会实现aware接口,如BeanFactoryAware、BeanNameAware等。

总的来说就是通过aware的具体实现子类,我们可以设置bean的一系列操作。

4.7.2.7 创建Bean

  创建好的bean会放入Map(单例池/一级缓存)中

context.getBean("bean的名字");时,会到一级缓存中查询,有就返回,没有就生产。

4.7.2.8 扩展接口

4.7.2.8.1 BeanFactoryPostProcessor接口

@FunctionalInterface
public interface BeanFactoryPostProcessor {
    void postProcessBeanFactory(ConfigurableListableBeanFactory BeanFactory) throws BeansException;
}

 BeanFactoryPostProcessor中的postProcessBeanFactory()方法,直接传来一个

4.7.2.8.2 BeanDefinitionRegistryPostProcessor

源码定义如下:

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
    void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry var1) throws BeansException;
}

BeanDefinitionRegistryPostProcessor的作用是注册BeanDefinition,也就是注册了Bean

Spring-MyBatis中的Mapper是接口,动态代理

4.7.2.8.3 BeanPostProcessor

 BeanPostProcessor(bean的后置处理器)主要用在初始化前后

BeanPostProcessor有很多子接口

4.7.3 Bean生命周期

4.7.3.1 简化版本

1、实例化bean,当客户向容器请求一个尚未初始化的bean时,容器就会调用doCreateBean()方法进行实例化,实际上就是利用反射来创建一个bean对象

2、当bean对象创建出来后就对bean对象进行属性填充,也就是注入这个bean依赖的其他对象

3、属性填充完成后,进行初始化bean操作

         a、执行Aware接口方法,Spring会检查该bean对象是否实现了xxxAware接口,通过Aware类型的接口,我们可以拿到spring容器的一些资源,如实现了BeanNameAware接口就可以获取BeanName等等

        b、执行BeanPostProcessor的前置处理方法postProcessBeforeInitialization(),对Bean进行一些自定义的前置处理

        c、判断bean是否实现了InitialalizationBean接口,如果实现了,将会执行InitialalizationBean的afterPropertiesSet()初始化方法

        d、执行用户自定义的初始化方法,如init-method等

        e、执行BeanPostProcessor的后置处理方法postProcessAfterInitialization()

4、销毁

        a、首先判断Bean是否实现了DestructionAwareBeanPostProcessor接口,如果实现了,则执行DestructionAwareBeanPostProcessor后置处理器的销毁方法

        b、其次判断Bean是否实现了DisposableBean接口,如果实现了就会调用其实现的destroy()方法

        c、最后判断Bean是否配置了destroy-method方法,如果有就调用其配置的销毁方法

4.7.3.2 详细版本

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {

//bean
 protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
        }
//如果缓存中不存在,则调用createBeanInstance创建一个BeanWrapper(bean的包装类)
        if (instanceWrapper == null) {
//bean的实例化
            instanceWrapper = this.createBeanInstance(beanName, mbd, args);
        }
//初始化bean实例
 Object exposedObject = bean;

//----------------省略-----------
//属性填充
            this.populateBean(beanName, mbd, instanceWrapper);
//初始化bean,如执行aware接口的子类,执行init-method方法,BeanPostProcesso后置增强等
            exposedObject = this.initializeBean(beanName, exposedObject, mbd);


//销毁不在AbstractAutowireCapableBeanFactory 类,在DisposableBeanAdapter类中


}

 initializeBean

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged(() -> {
//先执行aware的子类
                this.invokeAwareMethods(beanName, bean);
                return null;
            }, this.getAccessControlContext());
        } else {
            this.invokeAwareMethods(beanName, bean);
        }

          Object wrappedBean = bean;
            if (mbd == null || !mbd.isSynthetic()) {
//执行beanPostProcessor后置处理器的前置方法BeanPostProcessorsBeforeInitialization
                wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
            }
//中间执行init-method
        try {
            this.invokeInitMethods(beanName, wrappedBean, mbd);
        } catch (Throwable var6) {
            throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
        }
//最后执行BeanPostProcessorsAfterInitialization
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }

 invokeAwareMethods

    private void invokeAwareMethods(String beanName, Object bean) {

        if (bean instanceof Aware) {
//如果bean实现了BeanNameAware,那bean内部可以获取到beanName属性
            if (bean instanceof BeanNameAware) {
                ((BeanNameAware)bean).setBeanName(beanName);
            }
//其他同理
            if (bean instanceof BeanClassLoaderAware) {
                ClassLoader bcl = this.getBeanClassLoader();
                if (bcl != null) {
                    ((BeanClassLoaderAware)bean).setBeanClassLoader(bcl);
                }
            }

            if (bean instanceof BeanFactoryAware) {
                ((BeanFactoryAware)bean).setBeanFactory(this);
            }
        }

    }

 invokeInitMethods

  protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd) throws Throwable {
//InitialalizationBean接口,如果实现了,将会执行InitialalizationBean的afterPropertiesSet()初始化方法
        boolean isInitializingBean = bean instanceof InitializingBean;
        if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
            if (this.logger.isTraceEnabled()) {
                this.logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
            }

            if (System.getSecurityManager() != null) {
                try {
//执行afterPropertiesSet()
                    AccessController.doPrivileged(() -> {
                        ((InitializingBean)bean).afterPropertiesSet();
                        return null;
                    }, this.getAccessControlContext());
                } catch (PrivilegedActionException var6) {
                    throw var6.getException();
                }
            } else {
                ((InitializingBean)bean).afterPropertiesSet();
            }
        }
//用户自定义的初始化方法
        if (mbd != null && bean.getClass() != NullBean.class) {
            String initMethodName = mbd.getInitMethodName();
            if (StringUtils.hasLength(initMethodName) && (!isInitializingBean || !"afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) {
//用户自定义的方法
                this.invokeCustomInitMethod(beanName, bean, mbd);
            }
        }

    }

 DisposableBeanAdapter

//销毁
class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
 public void destroy() {
        if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
            Iterator var1 = this.beanPostProcessors.iterator();

            while(var1.hasNext()) {
//先查看DestructionAwareBeanPostProcessor接口
                DestructionAwareBeanPostProcessor processor = (DestructionAwareBeanPostProcessor)var1.next();
//如果实现了,则执行DestructionAwareBeanPostProcessor后置处理器的销毁方法
                processor.postProcessBeforeDestruction(this.bean, this.beanName);
            }
        }
//接着看是否实现了DisposableBean接口
              if (System.getSecurityManager() != null) {
                   AccessController.doPrivileged(() -> {
//如果实现了就调用接口的destroy方法
                       ((DisposableBean)this.bean).destroy();
                            
                }
              }
//最后判断是否有用户自定义的销毁方法
           if (this.destroyMethod != null) {
            this.invokeCustomDestroyMethod(this.destroyMethod);
        } else if (this.destroyMethodName != null) {
            Method methodToInvoke = this.determineDestroyMethod(this.destroyMethodName);
            if (methodToInvoke != null) {
//调用用户自定义的销毁方法
                this.invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));
            }
        }
}

Spring的理解

Spring是什么?

框架:方便开发,整合其他框架

容器:管理bean

生态:目前主流的Java开发,都会用到Java全家桶。Springboot、Springcloud等框架都是对Spring的扩展实现。

11张流程图搞定 Spring Bean 生命周期 - 知乎

4.7.3.3 循环依赖

4.7.3.3.1 循环依赖问题

4.7.3.3.2 解决方案:三级缓存

singletonObject(一级缓存):存放实例化 -> 代理 -> 属性注入 ->初始化后的对象

earlySingletonObjects(二级缓存):存放实例化 -> 代理 -> 属性注入 ->初始化后的对象

singletonFactories(三级缓存):存放对象工厂,可以从对象工厂中拿到还未属性注入的对象(对象工厂便于创建代理对象)

4.7.3.3.3 流程

当getBean(),获取bean时,spring会先到一级缓存中找,没有再去二级缓存,若二级缓存还没有就会创建一个对应的工厂对象

4.7.4 AOP

单例bean

Spring中的Bean对象默认是单例的,框架并没有对Bean进行多线程封装处理

单例bean是指IOC容器中就只有这么一个bean,是全局共享的。分为有状态bean和无状态bean。

有状态的bean

就是有实例变量的对象,可以保存数据(有状态就是有数据存储功能),是线程不安全的。每个用户都有自己特有的实例,在用户的生命周期中,bean保存了用户的信息,即为“偶状态”;一旦用户衰亡(调用结束),bean的生命周期也随之结束。即每个用户最初都会得到一个初始的bean。

无状态的bean

就是没有实例变量的对象,不能保存数据,是不变类,是线程安全的。bean一旦实例化就被加进会话池中,各个用户都可以共用。即使用户已经消亡,bean的生命期也不一定结束,它可能依然存在于会话池中,供其他用户调用。由于没有特定的用户,那么也就不能保持某一用户的状态,所以叫无状态bean。但无状态会话bean 并非没有状态,如果它有自己的属性(变量),那么这些变量就会受到所有调用它的用户的影响,这是在实际应用中必须注意的。

 实例变量

java类的成员变量有俩种:一种是被static关键字修饰的变量,叫类变量或者静态变量;另一种没有static修饰,为实例变量。

class Car{

private name;   //这就是实例变量

public void 方法(){};

}

当一个对象被实例化之后,每个实例变量的值就跟着确定;

实例变量在对象创建的时候创建,在对象被销毁的时候销毁;

如果Bean是有状态的,那就需要开发人员自己来进行线程安全的保证,最简单的办法就是改变bean的作用域 把 "singleton"改为’‘protopyte’ 这样每次请求Bean就相当于是 new Bean() 这样就可以保证线程的安全了。

无状态就是不会存储数据,试想controller,service和dao本身并不是线程安全的,只是调用里面的方法,而且多线程调用一个实例的方法,会在内存中复制遍历,这是自己线程的工作内存,是最安全的。因此在进行使用的时候,不要在bean中声明任何有状态的实例变量或者类变量,如果必须如此,也推荐大家使用ThreadLocal把变量变成线程私有,如果bean的实例变量或者类变量需要在多个线程之间共享,那么就只能使用synchronized、lock、cas等这些实现线程同步的方法。但是一旦使用了synchronized、lock等线程同步方法,又会降低系统效率。

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

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

相关文章

08-09-Zookeeper客户端使用与经典应用场景

Zookeeper 集群模式&#xff1a; Zookeeper 集群模式一共有三种类型的角色 Leader: 处理所有的事务请求&#xff08;写请求&#xff09;&#xff0c;可以处理读请求&#xff0c;集群中只能有一个Leader Follower&#xff1a;只能处理读请求&#xff0c;同时作为 Leader的候选节…

实现 effect reactive 依赖收集 触发依赖

03_01_实现 effect & reactive & 依赖收集 & 触发依赖 一、reactivity happy path 首先我们知道reactivity的happy path&#xff08;核心逻辑&#xff09;就是: 通过reactive定义响应式变量&#xff0c;然后通过effect去收集响应式变量的依赖&#xff0c;然后实现…

20221225英语学习

今日新词 giant adj.巨大的&#xff1b;超群的 appreciate v.欣赏&#xff0c;赏识&#xff1b;感激&#xff1b;理解&#xff0c;意识到&#xff1b;增值 invasive adj.侵入的&#xff0c;侵略的&#xff1b;开刀的 dispel vt.驱散&#xff0c;驱逐&#xff1b;消除 equa…

【2008NOIP普及组】T4. 立体图 试题解析

【2008NOIP普及组】T4. 立体图 试题解析 时间限制: 1000 ms 内存限制: 65536 KB 提交数: 778 通过数: 542 【题目描述】 小渊是个聪明的孩子,他经常会给周围的小朋友讲些自己认为有趣的内容。最近,他准备给小朋友讲解立体图,请你帮他画出立体图。 小渊有一块面…

Windows下安装RabbitMQ

目录 安装Erlang环境 下载地址&#xff1a;https://erlang.org/download/ 下载后直接双击.exe安装即可。 安装完成后&#xff0c;创建环境变量。 安装完成后创建一个名叫ERLANG_HOME的环境变量&#xff0c;其指向erlang的安装目录&#xff1b; 将%ERLANG_HOME%\bin加入到Pa…

node.js+uni计算机毕设项目基于微信小程序订餐系统(程序+小程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程。欢迎交流 项目运行 环境配置&#xff1a; Node.js Vscode Mysql5.7 HBuilderXNavicat11VueExpress。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等…

2022 IoTDB Summit:Dr.Feinauer《Apache IoTDB 在德国汽车生产线多级数据同步中的应用实践》...

12 月 3 日、4日&#xff0c;2022 Apache IoTDB 物联网生态大会在线上圆满落幕。大会上发布 Apache IoTDB 的分布式 1.0 版本&#xff0c;并分享 Apache IoTDB 实现的数据管理技术与物联网场景实践案例&#xff0c;深入探讨了 Apache IoTDB 与物联网企业如何共建活跃生态&#…

【金猿人物展】树根互联COO黄路川:从“灯塔工厂”到“数字领航”,工业互联网操作系统助推新型工业化...

‍黄路川本文由树根互联联合创始人、COO黄路川撰写并投递参与“数据猿年度金猿策划活动——2022大数据产业趋势人物榜单及奖项”评选。‍数据智能产业创新服务媒体——聚焦数智 改变商业大数据时代&#xff0c;数字资产已经成为工业企业最核心的资产&#xff0c;成为企业数字化…

并发知识体系大全:贡献一波我平时学习/总结笔记/思维脑图+线程

这个世界都是并发的&#xff0c;编程里更是这样&#xff0c;俗话说&#xff1a;并发知识大&#xff0c;一口吃不下。想成为一名优秀的 Java 开发&#xff0c;学好并发&#xff0c;绝对是你走入高薪行列的必备能力之一。 并发涉及的知识点&#xff0c;其实十分琐碎。学完记不住…

2022圣诞代码(圣诞树+圣诞老人)

文章目录前言使用方法圣诞树圣诞老人前言 圣诞节里的喜悦&#xff0c;飘扬万里&#xff1b;圣诞树上的星星&#xff0c;璀璨耀眼&#xff1b;圣诞星空绽放的烟花&#xff0c;迎来吉祥&#xff1b;圣诞钟声奏响的旋律&#xff0c;传递欢乐&#xff1b;圣诞老人送给你的礼物&…

数据结构---位图算法

位图算法将数据存储到位图中查询数据是否在位图中JAVA代码问题扩展这里所说的位图并不是像素图片的位图&#xff0c;而是内存中连续的二进制位&#xff08;bit&#xff09;所组成的数据结构&#xff0c; 该算法主要用于对大量整数做去重和查询操作。System.out.println(1L <…

地质灾害安全监测预警解决方案

一、方案背景 我国地质和地理环境复杂&#xff0c;气候条件时空差异大&#xff0c;地质灾害种类多、分布广、危害大&#xff0c;是世界上地质灾害最严重的国家之一。地质灾害来源于自然和人为作用下对地质环境的灾难性后果&#xff0c;主要包括崩塌、滑坡、泥石流、地面塌陷和…

RV1126笔记十六:吸烟行为检测及部署<三>

若该文为原创文章,转载请注明原文出处。 训练并测试(windows) 一、yolov5安装 1、下载rk优化后的yolov5 git clone https://github.com/airockchip/yolov5.git 下载后,我是放到E:\miniconda3\envs目录下,miniconda3是安装miniconda的目录。可以放到其他地方,后续操作需要…

语音处理的算法和方法研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Python pandas库|任凭弱水三千,我只取一瓢饮(7)

上一篇链接&#xff1a; Python pandas库&#xff5c;任凭弱水三千&#xff0c;我只取一瓢饮&#xff08;6&#xff09;_Hann Yang的博客-CSDN博客 to_系列函数&#xff1a;22个 &#xff08;12~22&#xff09; Function12 to_numpy(self, dtype: NpDtype | None None, co…

《网线制作》

前言&#xff1a; 随着计算机的快速发展&#xff0c; 现代 社会人们已经离不开网络&#xff0c;网络拉近了人们的距离&#xff0c;给人们提供了一个无需面对面就能够进行交流的平台&#xff0c;如今&#xff0c;网络已经渗透到生活的方方面面&#xff0c;购物、聊天、谈工作等…

【图卷积网络和知识提取】

When Pansharpening Meets Graph Convolution Network and Knowledge Distillation &#xff08;当全色锐化遇到图卷积网络和知识提取时&#xff09; 空洞卷积(Dilated/Atrous Convolution) 在本文中&#xff0c;我们提出了一种新颖的用于全色锐化的图卷积网络&#xff08;gra…

7. 表现层数据封装

表现层数据封装[TOC](表现层数据封装)1. 表现层响应数据的问题2. 定义ResponseResults类封装响应结果3. 定义Code类封装响应码4. 表现层数据封装返回Result对象5.postman发送请求结果1. 表现层响应数据的问题 ​ 目前表现层增删改方法返回true或者false表示是否成功&#xff0…

Kubernetes网络自学系列 | 网络虚拟化基石:network namespace

素材来源&#xff1a;《Kubernetes网络权威指南》 一边学习一边整理内容&#xff0c;并与大家分享&#xff0c;侵权即删&#xff0c;谢谢支持&#xff01; 附上汇总贴&#xff1a;Kubernetes网络自学系列 | 汇总_COCOgsta的博客-CSDN博客 1.1 网络虚拟化基石&#xff1a;netw…

【Pandas入门教程】如何计算汇总统计数据

如何计算汇总统计数据 来源&#xff1a;Pandas官网&#xff1a;https://pandas.pydata.org/docs/getting_started/intro_tutorials/index.html 笔记托管&#xff1a;https://gitee.com/DingJiaxiong/machine-learning-study 文章目录如何计算汇总统计数据导包数据准备【1】如何…