【Spring框架】Spring监听器的简介和基本使用

目录

一、观察者模式

1.1 模型介绍

1.2 观察者模式Demo

1.2.1 观察者实体

1.2.2 主题实体

1.2.3 测试代码

二、Spring监听器的介绍

2.1 事件(ApplicationEvent)

2.1.1 Spring内置事件

2.1.2 Spring内置事件

2.2 事件监听器(ApplicationListener)

2.2.1 事件监听器-基于接口

2.2.1.1 SmartApplicationListener

2.2.1.2 GenericApplicationListener

2.2.2 事件监听器-基于注解

2.3 事件发布者(ApplicationEventPublisher)

2.4 事件广播器(ApplicationEventMulticaster)

三、Spring监听器的使用

3.1 新建监听器

3.1.1 通过实现ApplicationListener接口创建监听器

3.1.2 使用@EventListener注解创建监听器

3.2 内置的事件类型

3.3 自定义事件与监听器Demo

3.3.1 构建两个自定义事件

3.3.2 构建监听

3.3.3 发布事件


一、观察者模式

Spring的监听器用到了观察者模式,工厂模式(EventListenerFactory),适配器模式(ApplicationListenerMethodAdapter),而其中最重要的就是基于观察者模式,它能实现事件与事件监听者直接的解耦。所以在讲解监听器之前,我们先讲一下观察者模式。

1.1 模型介绍

观察者模式(Observer Pattern)是一种行为设计模式,它用于在对象之间建立一对多的依赖关系。在该模式中,当一个对象的状态发生变化时,它会自动通知其依赖对象(称为观察者),使它们能够自动更新。

观察者模式的工作原理如下:

  1. 主题对象维护一个观察者列表,并提供方法用于添加和删除观察者。
  2. 当主题的状态发生变化时(监听到某种事件发生),它会遍历观察者列表,并调用每个观察者的通知方法。
  3. 观察者接收到通知后,根据通知进行相应的更新操作。

以我的理解,就是一个主题会去监听一种事件,和这个事件相关的观察者都会被加到这个主题对象中。当主题对象监听到这个事件发生了,就会去通知自己维护的所有观察者,这些观察者就回去执行相应的逻辑。也就是一种主题对应一种事件,要观察这个事件的观察者都添加到这个主题中,由主题去监听这个事件是否发生,事件发生后主题回去通知所有的观察者,观察者们再去执行相应的逻辑

观察者模式角色:

  • Subject:抽象主题(抽象被观察者),抽象主题角色把所有观察者对象保存在一个集合里,每个主题都可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象。
  • ConcreteSubject:具体主题(具体被观察者),该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知。
  • Observer:抽象观察者,是观察者者的抽象类,它定义了一个更新接口,使得在得到主题更改通知时更新自己。
  • ConcrereObserver:具体观察者,实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态。

1.2 观察者模式Demo

一个观察者模式demo包括以下部分:

  • 观察者实体
  • 主题实体

1.2.1 观察者实体

所以我们先写个观察者接口

interface Observer {void update();
}

再构建两个观察者实现类

// 具体观察者A
class ConcreteObserverA implements Observer {@Overridepublic void update() {System.out.println("ConcreteObserverA收到更新通知");}
}// 具体观察者B
class ConcreteObserverB implements Observer {@Overridepublic void update() {System.out.println("ConcreteObserverB收到更新通知");}
}

1.2.2 主题实体

然后定义主题接口

interface Subject {// 注册新的观察者void registerObserver(Observer observer);// 删除指定观察者void removeObserver(Observer observer);// 通知全部观察者void notifyObservers();
}

构建一个具体主题

// 具体主题
class ConcreteSubject implements Subject {// 一个主题维护多个观察者private List<Observer> observers = new ArrayList<>();@Overridepublic void registerObserver(Observer observer) {observers.add(observer);}@Overridepublic void removeObserver(Observer observer) {observers.remove(observer);}@Overridepublic void notifyObservers() {for (Observer observer : observers) {observer.update();}}public void doSomething() {System.out.println("主题执行某些操作...");// 执行操作后通知观察者notifyObservers(); }
}

1.2.3 测试代码

public class ObserverPatternDemo {public static void main(String[] args) {// 创建主题和观察者ConcreteSubject subject = new ConcreteSubject();Observer observerA = new ConcreteObserverA();Observer observerB = new ConcreteObserverB();// 注册观察者subject.registerObserver(observerA);subject.registerObserver(observerB);// 执行主题的操作,触发通知subject.doSomething();}
}

最后可以看到结果:

主题执行某些操作…

ConcreteObserverA收到更新通知

ConcreteObserverB收到更新通知

二、Spring监听器的介绍

Spring事件体系包括三个组件:

  1. 事件广播器(事件多播器、事件发布器),可以理解为就是applicationContext。
  2. 事件ApplicationEvent。
  3. 事件监听器ApplicationListener。

实现Spring事件机制主要有4个类:

  • ApplicationEvent:事件,每个实现类表示一类事件,可携带数据。
  • ApplicationListener:事件监听器,用于接收事件处理时间。
  • ApplicationEventMulticaster:事件管理者,用于事件监听器的注册和事件的广播。
  • ApplicationEventPublisher:事件发布者,委托ApplicationEventMulticaster完成事件发布。

2.1 事件(ApplicationEvent

事件(ApplicationEvent) 是特定事件监听器被触发的原因。

2.1.1 Spring内置事件

内置事件中由系统内部进行发布,只需自己注入监听器即可。

Spring容器启动的时候在不同阶段会发布不同事件,我们可以根据自己的需求进行监听。(阿里的nacos服务自动注册原理就是监听到web容器初始化完成事件,完成自动注册发现)。例如Spring容器启动完之后,会发布一个ContextRefreshedEvent事件,我们可以实现自己的监听器进行监听。

@Component
// 设置用于监听ContextRefreshedEvent事件的监听器
public class MyListener2 implements ApplicationListener<ContextRefreshedEvent> {@Overridepublic void onApplicationEvent(ContextRefreshedEvent event) {System.out.println("-----------------:"+event.getSource().getClass());}
}

可以使用Spring内置的事件来对注册到容器中的Bean进行拓展,重点看内置的ContextRefreshedEvent和ContextClosedEvent这两个事件,一个是在刚完成容器初始化的时候被发布的事件,一个是关闭容器时发布的事件。我们只要去编写监听这两个事件的监听器,来自定义实现一些逻辑,就能做到对注册到容器中的Bean进行拓展了。

内置的事件类型:

Event

说明

ContextRefreshedEvent

当容器被实例化或refreshed时发布。如调用refresh()方法,此处的实例化是指所有的bean都已被加载,后置处理器都被激活,所有单例bean都已被实例化,所有的容器对象都已准备好可使用。如果容器支持热重载,则refresh可以被触发多次(XmlWebApplicatonContext支持热刷新,而 GenericApplicationContext则不支持)

ContextStartedEvent

当容器启动时发布,即调用start()方法,已启用意味着所有的Lifecycle bean都已显式接收到了start 信号

ContextStoppedEvent

当容器停止时发布,即调用stop()方法,即所有的Lifecycle bean都已显式接收到了stop信号,关闭的容器可以通过start()方法重启

ContextClosedEven36

当容器关闭时发布,即调用close方法,关闭意味着所有的单例bean都已被销毁。关闭的容器不能被重启 或refresh

RequestHandledEvent

这只在使用spring的DispatcherServlet时有效,当一个请求被处理完成时发布

内置事件类型的继承体系:

2.1.2 Spring内置事件

事件类需要继承ApplicationEvent抽象类,代码如下:

public class BigEvent extends ApplicationEvent {private String name;public BigEvent(Object source, String name) {super(source);this.name = name;}public String getName() {return name;}
}

这里为了简单测试,所以写的很简单。

事件类其实就是一种很简单的pojo,除了需要继承ApplicationEvent也没什么了,这个类有一个构造方法需要调用super()方法。

2.2 事件监听器(ApplicationListener

事件监听器(ApplicationListener)对应于观察者模式中的观察者。作用为处理事件广播器发布的事件。

在Spring中监听器的实现主要有一下重要组件:

  • ApplicationListener接口:事件监听者,观察者;
  • ApplicationEvent抽象类:Spring 事件,记录事件源、事件内容、时间等数据;
  • @EventListener注解:除了实现ApplicationListener接口注册监听器,也可以使用注解的方式;
  • ApplicationEventPublisher接口:发布事件;

2.2.1 事件监听器-基于接口

Spring提供了继承于java.util.EventListener接口的应用监听器接口, ApplicationListener,此接口源码:

@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {/*** Handle an application event.* @param event the event to respond to*/void onApplicationEvent(E event);
}

使用接口实现监听器:

@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {/*** Handle an application event.* @param event the event to respond to*/void onApplicationEvent(E event);
}

事件监听器需要实现ApplicationListener接口,这是个泛型接口,泛型类类型就是事件类型,其次监听器是需要spring容器托管的bean,所以这里加了@component,只有一个方法,就是onApplicationEvent(),是事件发生后要触发的操作。

Spring还提供了对ApplicationListener接口的实现:SmartApplicationListener接口和GenericApplicationListener接口。

2.2.1.1 SmartApplicationListener

提供了监听器对泛型事件的支持,spring3.0 添加的。

源码:

public interface SmartApplicationListener extends ApplicationListener<ApplicationEvent>, Ordered {boolean supportsEventType(Class<? extends ApplicationEvent> var1);boolean supportsSourceType(Class<?> var1);
}

2.2.1.2 GenericApplicationListener

增强对泛型事件的支持(支持泛型方式不同与SmartApplicationListener),spring4.2 添加的。

源码:

public interface GenericApplicationListener extends ApplicationListener<ApplicationEvent>, Ordered {boolean supportsEventType(ResolvableType var1);boolean supportsSourceType(Class<?> var1);
}

2.2.2 事件监听器-基于注解

@Component
public class OrderEventListener {@EventListener(OrderEvent.class)public void onApplicationEvent(OrderEvent event) {if(event.getName().equals("减库存")){System.out.println("减库存.......");}}
}

注解是加到onApplicationEvent()方法上的(方法名可以自定义,这个方法就是监听器监听到事件发生后触发的执行逻辑)。

这里要注意,加注解的方法不能是private修饰的方法,否则会报错。

@EventListener的错误尝试:

道了@EventListener的原理,我们其实可以做一些猜测,如下:

methodA是正常的用法;

methodB方法的修饰符是private;

methodC则是监听的ContextRefreshedEvent,但下面方法的入参却是ContextClosedEvent;

后两者都有问题:

可以看到,编译器直接黄底提示了methodB的@EventListener注解,其实从前面我们已经猜到,因为最后我们的调用是由监听器ApplicationListenerMethodAdapter对象直接调用的方法ABC,所以方法必须可被其他对象调用,即public。

而后者会在执行广播响应事件时报参数非法异常也是意料之中。

2.3 事件发布者(ApplicationEventPublisher

事件发布者,职责为发布事件。

spring的ApplicationContext 本来就实现了ApplicationEventPublisher接口,因此应用上下文本来就是

一个事件发布者,在AbstractApplicationContext中实现了事件发布的业务。

上下文对象调用publishEvent()方法,将事件对象传入即可将该事件发布。

applicationContext.publishEvent(new HelloEvent(this,"lgb"));

事件发布之后就会被已经注册到Spring容器中对应的事件监听器监听到,会触发监听器onApplicationEvent()操作。

2.4 事件广播器(ApplicationEventMulticaster

Spring事件机制是观察者模式的一种实现,但是除了发布者和监听者者两个角色之外,还有一个EventMultiCaster的角色负责把事件转发给监听者。

事件发布器(ApplicationEventMulticaster)又叫事件发布器、事件多播器。对应于观察者模式中的被观察者/主题, 负责通知观察者。对外提供发布事件和增删事件监听器的接口,维护事件和事件监听器之间的映射关系,并在事件发生时负责通知相关监听器。

其工作流程如下:

EventMultiCaster注册着所有的Listener,在上面发布事件的代码中发布者调用applicationEventPublisher.publishEvent(msg); 是会将事件发送给了EventMultiCaster,然后EventMultiCaster根据事件类型决定转发给那个Listener。

讲完了Spring事件体系中的三个组件,我们就明白了他们之间的关系和运作流程。下面我们再详细讲一下如何使用它。

三、Spring监听器的使用

3.1 新建监听器

3.1.1 通过实现ApplicationListener接口创建监听器

import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;@Component
public class MyContextRefreshedListener implements ApplicationListener<ContextRefreshedEvent> {@Overridepublic void onApplicationEvent(ContextRefreshedEvent event) {System.out.println("应用程序上下文已刷新");// 在这里可以执行一些初始化操作}
}
  • 我们创建了一个名为MyContextRefreshedListener的监听器,它实现了ApplicationListener接口,并且传入的泛型是ContextRefreshedEvent,这意味着这个监听器监听的事件类型是ContextRefreshedEvent。MyContextRefreshedListener重写了 onApplicationEvent 方法。因为Spring会在容器refresh()时发布ContextRefreshedEvent事件,所以onApplicationEvent方法在应用程序上下文被刷新时触发。
  • 使用 @Component 注解将该监听器声明为一个Spring管理的组件,这样Spring会自动将其纳入到应用程序上下文中,并在适当的时候触发监听。

3.1.2 使用@EventListener注解创建监听器

除了手动写个类外,我们也可以找个现成的类,该类不需要继承或实现任何其他类,只需要在它的某个方法上加上 @EventListener 注解就可以实现监听器的功能,如下:

@Component
public class MyListener {@EventListener(ContextRefreshedEvent.class)public void methodA(ContextRefreshedEvent event) {System.out.println("应用程序上下文已刷新");// 在这里可以执行一些初始化操作}
}
  • 在一个现有的类的某个方法上,加上@EventListener(ContextRefreshedEvent.class),Spring会在加载这个类时,为其创建一个监听器,这个监听器监听的事件类型是ContextRefreshedEvent,当此事件发生时,将触发执行该方法methodA。
  • 使用 @Component 注解将该类声明为一个Spring管理的组件,这样Spring会自动将其纳入到应用程序上下文中,并在适当的时候触发监听。
  • 我们可以在这个类中写上多个方法,每个方法通过注解监听着不同的事件类型,这样我们就仅需使用一个类,却构建了多个监听器。

上述两种方法的效果是一样的。那么最后,我们就完成了Spring中一个内置监听器的简单示例:当启动一个基于Spring的应用程序时,当应用程序上下文被刷新时,ContextRefreshedEvent事件将被触发,然后MyContextRefreshedListener监听器的onApplicationEvent方法将被调用。

3.2 内置的事件类型

我们在demo中使用了一个 ContextRefreshedEvent 的事件,这个事件是Spring内置的事件,除了该事件,Spring还内置了一些其他的事件类型,分别在以下情况下触发:

  • ContextRefreshedEvent:

        当应用程序上下文被刷新时触发。这个事件在ApplicationContext初始化或刷新时被发布,适用于执行初始化操作和启动后的后续处理。例如,初始化缓存、预加载数据等。

  • ContextStartedEvent:

当应用程序上下文启动时触发。这个事件在调用ApplicationContext的start()方法时被发布,适用于在应用程序启动时执行特定的操作。例如,启动定时任务、启动异步消息处理等。

  • ContextStoppedEvent:

当应用程序上下文停止时触发。这个事件在调用ApplicationContext的stop()方法时被发布,适用于在应用程序停止时执行清理操作。例如,停止定时任务、关闭数据库连接等。

  • ContextClosedEvent:

当应用程序上下文关闭时触发。这个事件在调用ApplicationContext的close()方法时被发布,适用于在应用程序关闭前执行最后的清理工作。例如,释放资源、保存日志等。

  • RequestHandledEvent:

在Web应用程序中,当一个HTTP请求处理完成后触发。这个事件在Spring的DispatcherServlet处理完请求后被发布,适用于记录请求日志、处理统计数据等。

  • ApplicationEvent:

这是一个抽象的基类,可以用于定义自定义的应用程序事件。你可以创建自定义事件类,继承自ApplicationEvent,并定义适合你的应用场景的事件类型。

这些内置监听器是由Spring框架自动发布的。不需要程序员去发布。

3.3 自定义事件与监听器Demo

在学习完上面的内容后,我们现在可以手动写个Spring的事件,以及对应的监听器的demo了

3.3.1 构建两个自定义事件

Spring通过继承ApplicationEvent抽象类来创建自定义事件。下面我们来建立一个继承自ApplicationEvent的自定义事件类。

// 事件A
public class CustomEventA extends ApplicationEvent {private String message;public CustomEventA(Object source, String message) {super(source);this.message = message;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}
}// 事件B
public class CustomEventB extends ApplicationEvent {private String message;public CustomEventB(Object source, String message) {super(source);this.message = message;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}
}

3.3.2 构建监听

我们选用@EventListener注解来实现监听器。

@Component
public class MyListener {@EventListener(CustomEventA.class)public void methodA(CustomEventA event) {System.out.println("========我监听到事件A了:" + event.getMessage());// 在这里可以执行一些其他操作}@EventListener(CustomEventB.class)public void methodB(CustomEventB event) {System.out.println("========我监听到事件B了:" + event.getMessage());// 在这里可以执行一些其他操作}
}

3.3.3 发布事件

@Component
// 这里将这个CustomEvent事件发布器也设置成一个事件监听器了,去监听ContextRefreshedEvent事件,当这个时间发生之后就会自动去发布CustomEvent事件
public class CustomEventPublisher implements ApplicationContextAware, ApplicationListener<ContextRefreshedEvent> {private ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;}// 利用容器刷新好的消息作为触发,去发布两条自定义的事件@Overridepublic void onApplicationEvent(ContextRefreshedEvent event) {// 创建事件CustomEventA eventA = new CustomEventA(applicationContext , "我是AAAA");CustomEventB eventB = new CustomEventB(applicationContext , "我是BBBB");// 发布事件applicationContext.publishEvent(eventA);applicationContext.publishEvent(eventB);}
}

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

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

相关文章

三大方法快速发现商业规律

文章目录 三大方法快速发现商业规律一、市场调研二、数据分析三、案例分析 &#x1f4d5;我是廖志伟&#xff0c;一名Java开发工程师、Java领域优质创作者、CSDN博客专家、51CTO专家博主、阿里云专家博主、清华大学出版社签约作者、产品软文创造者、技术文章评审老师、问卷调查…

PHP LFI 利用临时文件Getshell

PHP LFI 利用临时文件 Getshell 姿势-安全客 - 安全资讯平台 LFI 绕过 Session 包含限制 Getshell-安全客 - 安全资讯平台 目录 PHP LFI 利用临时文件Getshell 临时文件 linux 和 windows的 临时文件存储规则 linux和windows对临时文件的命名规则 PHPINFO()特性 原理 条…

Python点击exe后报错:Failed to execute script xxxx问题的解决办法

最近工作在弄人脸识别的问题&#xff0c;从gitee来pull了一个但是发现报了一个Failed to execute script XXX的问题 造成这个问题的原因是执行文件exe存放的目录不对&#xff0c;可能在打包前exe文件并不是存在在这个位置。 解决方案将exe文件尝试存在在不同目录下&#xff…

详解Pinia和Vuex

一、vuex介绍 1.什么是vuex&#xff1f;为什么要使用vuex? Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 库。它采用集中式存储管理应用的所有组件的状态&#xff0c;并以相应的规则保证状态以一种可预测的方式发生变化。 在vue最重要的就是数据驱动和组件化&#x…

Qt之submodule编译

工作中会遇到这样一种情况&#xff1a;qt应用程序在运行时提示找不到某个qt的动态库。我遇到的是缺少libQt5Websocket.so&#xff0c;因为应用程序是在x86平台银河麒麟v10上开发&#xff0c;能够正常编译运行&#xff0c;然后移植到rk3588&#xff08;aarch64架构&#xff09;上…

NeuroImage | 右侧颞上回在语义规则学习中的作用:来自强化学习模型的证据

在现实生活中&#xff0c;许多规则的获取通常需要使用语言作为桥梁&#xff0c;特别是语义在信息传递中起着至关重要的作用。另外&#xff0c;个体使用的语言往往具有明显的奖励和惩罚元素&#xff0c;如赞扬和批评。一种常见的规则是寻求更多的赞扬&#xff0c;同时避免批评。…

【翻译】Efficient Data Loader for Fast Sampling-Based GNN Training on Large Graphs

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhang.cn] 此内容为机器翻译的结果&#xff0c;若有异议的地方&#xff0c;建议查看原文。 机器翻译的一些注意点&#xff0c;比如&#xff1a; 纪元、时代 > epoch工人 > worker火车、培训、训练师 > train Effic…

c# 弹出背景透明图

1. 在窗体中添加 picturebox 控件 2. 在 picturebox 中添加 “png ” 背景透明图&#xff0c;或者GIF图&#xff0c;属性设置如下 3. 在窗体初始化中&#xff0c;添加如下代码 this.BackColor Color.LimeGreen; this.TransparencyKey Color.LimeGreen; 此功能可以用来展示…

【Vue面试题三十】、vue项目本地开发完成后部署到服务器后报404是什么原因呢?

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 面试官&#xff1a;vue项目本地开发完成后部…

一卷到底,大明哥带你横扫 Netty

上一个死磕 Java 专栏【死磕 NIO】(当然写的不是很好&#xff0c;争取今年将它重写一遍)是**【死磕 Netty】**的铺垫&#xff0c;对于我们 Java 程序员而言&#xff0c;我们在实际开发过程一般都不会直接使用 Java NIO 作为我们的网络编程框架&#xff0c;因为写出一套高质量的…

基于和声优化的BP神经网络(分类应用) - 附代码

基于和声优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码 文章目录 基于和声优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码1.鸢尾花iris数据介绍2.数据集整理3.和声优化BP神经网络3.1 BP神经网络参数设置3.2 和声算法应用 4.测试结果&#xff1a;5.M…

内网渗透——隧道代理

文章目录 代理代理使用场景VPS建立隧道frpMSF木马生成监听开启frp服务端和客户端执行exe木马文件 代理 实验环境&#xff1a; 攻击机kali&#xff1a;192.168.188.133&#xff08;NAT模式&#xff09; 模拟的公网服务器&#xff08;本机&#xff09;&#xff1a;10.9.75.239 …

kube-controller-manager和kube-scheduler不能正常启动

kube-controller-manager-k8s-worker01和kube-scheduler-k8s-worker01没有启动起来 原因&#xff1a; 解决&#xff1a;进入/etc/kubernetes/manifests 编辑 将镜像地址修改为 然后重启kubelet&#xff1a;systemctl restart kubelet.service

freefilesync文件同步软件

下载 下载链接 https://freefilesync.org/download.php 往下拉&#xff0c;看到下载的链接 下载windows版本 下载地址&#xff1a; https://freefilesync.org/download/FreeFileSync_13.0_Windows_Setup.exe 直接复制到浏览器中访问就能下载 安装 双击安装包&#xff0c;一路默…

Megatron-LM GPT 源码分析(二) Sequence Parallel分析

引用 本文基于开源代码 https://github.com/NVIDIA/Megatron-LM &#xff0c;延续上一篇Megatron-LM GPT 源码分析&#xff08;一&#xff09; Tensor Parallel分析 通过对GPT的模型运行示例&#xff0c;从三个维度 - 模型结构、代码运行、代码逻辑说明 对其源码做深入的分析。…

zookeeper应用场景(二)

单机环境下可以利用jvm级别的锁&#xff0c;比如synchronized、Lock等来实现锁&#xff0c;如果是多机部署就需要一个共享数据存储区域来实现分布式锁 一、分布式锁实现方式 1、基于数据库实现分布式锁 可以用数据库唯一索引来实现 2、基于redis实现分布式锁 redis实现的分…

【Vue面试题二十六】、SSR解决了什么问题?有做过SSR吗?你是怎么做的?

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 面试官&#xff1a;SSR解决了什么问题&…

回归预测 | MATLAB实现IBES-ELM基于改进的秃鹰搜索优化算法优化极限学习机的数据回归预测(多指标,多图)

回归预测 | MATLAB实现IBES-ELM 基于改进的秃鹰搜索优化算法优化极限学习机的数据回归预测&#xff08;多指标&#xff0c;多图&#xff09; 目录 回归预测 | MATLAB实现IBES-ELM 基于改进的秃鹰搜索优化算法优化极限学习机的数据回归预测&#xff08;多指标&#xff0c;多图&a…

变分自动编码器 (VAE)02/2 PyTorch 教程

一、说明 在自动编码器中&#xff0c;来自输入数据的信息被映射到固定的潜在表示中。当我们旨在训练模型以生成确定性预测时&#xff0c;这特别有用。相比之下&#xff0c;变分自动编码器&#xff08;VAE&#xff09;将输入数据转换为变分表示向量&#xff08;顾名思义&#xf…

服务器崩溃前的数据拯救实践

前言 在服务器的VMWARE ESXi系统环境中&#xff0c;我们经常需要创建虚拟机来运行各种应用程序。然而&#xff0c;服务器如果偶尔出现自动重启以及紫屏报错的问题&#xff0c;说明服务器内部出现了故障&#xff0c;一般情况下重启机器能够解决问题&#xff0c;但时间一长&…