当前位置: 首页 > news >正文

Spring AOP技术

1.AOP基本介绍

AOP 的全称 (aspect oriented programming) ,面向切面编程。
1.和传统的面向对象不同。 面向切面编程是根据自我的需求,将切面类的方法切入到其他的类的方法中。(这么说抽象吧!来张图来解释。)
如图

传统的面向对象方法是 对象.方法()然后被调用

面向切面编程是什么呢? 

首先满足 @1 类的这个方法是通过动态代理实现的比如有个A.say()方法。

                 然后有一个切面类B,这个类也有许多方法比如study(),但是不同的是,这个类中的方法study(),可以插入到A.say()的方法前后进行。 当A.say()被调用的时候,切面类B的study()方法就会被自动调用。

                这就和传统的直接调用B.study()方法不同,切面类的方法是直接插入到另外一个动态代理类的方法的前后的。

AOP的核心概念


面向切面编程(AOP)是一种编程范式,它允许开发者将横切关注点(如日志记录、事务管理、安全性等)与业务逻辑分离,从而提高代码的模块化和可维护性。在Java中,AOP通常通过使用框架如Spring来实现。

介绍AOP的关键术语

切面(Aspect):切面是封装横切关注点的模块。它包含了一组通知(Advice)和切入点(Pointcut)。
连接点(Joinpoint):在程序执行过程中的特定点,如方法的调用或执行,异常的抛出等。
切点(Pointcut):切点是定义在哪些连接点上应用通知的规则。
通知(Advice):通知是在切点上执行的代码,它定义了在连接点上执行的逻辑,如前置、后置、环绕等。
解释AOP的几种通知类型

前置(Before):在方法执行前执行的通知。
后置(After):在方法执行后执行的通知,无论方法是否成功执行。
环绕(Around):在方法调用前后都可以执行的通知,可以控制方法的调用过程。
异常(Throws):在方法抛出异常后执行的通知。
最终(AfterReturning):在方法正常返回后执行的通知。

2.AOP的快速入门

在xml配置下:

    <context:annotation-config/><context:component-scan base-package="aspectj"/><!--启用基于注解方式的AOP功能--><aop:aspectj-autoproxy proxy-target-class="true"/>

【Spring进阶系列丨第十篇】基于注解的面向切面编程(AOP)详解_spring 切面 注解-CSDN博客

3.AOP的切入表达式

语法细节

注意第一个*是包含了任意的权限修饰符和返回值。

方法说明

 注意细节

1. 切入表达式也可以指向类的方法 , 这时切入表达式会对该类 / 对象生效
2. 切入表达式也可以指向接口的方法 , 这时切入表达式会对实现了接口的类 / 对象生效
3. 切入表达式也可以对没有实现接口的类,进行切入 (因为Spring的CGLIB)。

 4.JoinPoint连接点

作用:通过 JoinPoint 可以获取到调用方法的签名 signature
方法:

// 获取目标方法名

joinPoint.getSignature().getName(); 

// 获取目标方法所属类的简单类名
joinPoint.getSignature().getDeclaringType().getSimpleName(); 

// 获取目标方法所属类的类名
joinPoint.getSignature().getDeclaringTypeName();

// 获取目标方法声明类型(public、private、protected)
joinPoint.getSignature().getModifiers(); 

// 获取传入目标方法的参数,返回一个数组
Object[] args = joinPoint.getArgs(); 

// 获取被代理的对象
joinPoint.getTarget(); 

// 获取代理对象自己
joinPoint.getThis(); 

 在如下代码中要将beforeMethod()方法切入到aspectj包下的SmartDog类的getSum()下


@Before(value = "execution(public float aspectj.SmartDog.getSum(float, float))")
public void beforeMethod(JoinPoint joinPoint){
joinPoint.getSignature().getName(); // 获取目标方法名
joinPoint.getSignature().getDeclaringType().getSimpleName(); // 获取目标方法所属类的简单类名
joinPoint.getSignature().getDeclaringTypeName(); // 获取目标方法所属类的类名
joinPoint.getSignature().getModifiers(); // 获取目标方法声明类型(public、private、protected)
Object[] args = joinPoint.getArgs(); // 获取传入目标方法的参数,返回一个数组
joinPoint.getTarget(); // 获取被代理的对象
joinPoint.getThis(); // 获取代理对象自己
}

5.返回,异常,环绕通知返回结果

//返回通知@AfterReturning(value = "execution(public float aspectj.SmartDog.getSum(float, float))", returning = "res")public void showSuccessEndLog(JoinPoint joinPoint, Object res) {Signature signature = joinPoint.getSignature();System.out.println("SmartAnimalAspect-切面类showSuccessEndLog()-方法执行正常结束-日志-方法名-" + signature.getName() + " 返回的结果是=" + res);}//异常通知@AfterThrowing(value = "execution(public float aspectj.SmartDog.getSum(float, float))", throwing = "throwable")public void showExceptionLog(JoinPoint joinPoint, Throwable throwable) {Signature signature = joinPoint.getSignature();System.out.println("SmartAnimalAspect-切面类showExceptionLog()-方法执行异常-日志-方法名-" + signature.getName() + " 异常信息=" + throwable);}

6.切入点表达式重用

在这些切入方法里面,如果是作用于同一个方法,就会让切入表达式感到重复和冗余,于是为了统一管理切入点表达式,可以使用切入点表达式重用技术

package aspectj;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import java.util.Arrays;/*** @version 1.0* 这是一个切面类*/
@Aspect
@Component("smartAnimalAspect")
public class SmartAnimalAspect {//    切入表达式重用技术@Pointcut(value = "execution(public float aspectj.SmartDog.getSum(float, float))")public void mypointcut(){}//给SmartDog配置前置,返回,异常,最终通知//解读//1.@Before表示我们目标对象执行前要执行的哪个方法//2.value = "execution(public float aspectj.SmartDog.getSum(float, float))"// 是指定切入到哪个类的哪个方法 形式是:访问修饰符 返回类型 全类名.方法名(形参列表) execution是执行的意思//  JoinPoint joinPoint 在底层执行的时候,由Aspectj切面框架,会给该切入方法传入jointPoint对象//  通过该对象可以获得相关的信息。//前置通知@Before(value = "mypointcut()")public void showBeginLog(JoinPoint joinPoint) {//通过连接点对象joinPoint 可以获取方法签名Signature signature = joinPoint.getSignature();System.out.println("SmartAnimalAspect-切面类showBeginLog()[使用的myPointCut()]-方法执行前-日志-方法名-" + signature.getName() + "-参数 "+ Arrays.asList(joinPoint.getArgs()));}//返回通知@AfterReturning(value = "mypointcut()",returning = "res")public void showSuccessEndLog(JoinPoint joinPoint, Object res) {Signature signature = joinPoint.getSignature();System.out.println("SmartAnimalAspect-切面类showSuccessEndLog()-方法执行正常结束-日志-方法名-" + signature.getName() + " 返回的结果是=" + res);}//异常通知@AfterThrowing(value = "mypointcut()",throwing = "throwable")public void showExceptionLog(JoinPoint joinPoint, Throwable throwable) {Signature signature = joinPoint.getSignature();System.out.println("SmartAnimalAspect-切面类showExceptionLog()-方法执行异常-日志-方法名-" + signature.getName() + " 异常信息=" + throwable);}//最终通知@After(value = "mypointcut()")public void showFinallyEndLog(JoinPoint joinPoint) {Signature signature = joinPoint.getSignature();System.out.println("SmartAnimalAspect-切面类showFinallyEndLog()-方法最终执行完毕-日志-方法名-" + signature.getName());}}

 7.切面优先级问题

切面优先级问题 :
如果同一个方法,有多个切面在同一个切入点切入,那么执行的优先级如何控制 .
基本语法
@order(value=n) 来控制 n 值越小,优先级越高 .

举例
切面类1(优先执行)

package aspectj;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.util.Arrays;/*** @version 1.0* 这是一个切面类*/
@Order(value = 1)
@Aspect
@Component("smartAnimalAspect")
public class SmartAnimalAspect {//    切入表达式重用技术@Pointcut(value = "execution(public float aspectj.SmartDog.getSum(float, float))")public void mypointcut(){}//前置通知
//    @Before(value = "execution(public float aspectj.SmartDog.getSum(float, float))")@Before(value = "mypointcut()")public void showBeginLog(JoinPoint joinPoint) {//通过连接点对象joinPoint 可以获取方法签名Signature signature = joinPoint.getSignature();System.out.println("1前置通知" + signature.getName() + "-参数 "+ Arrays.asList(joinPoint.getArgs()));}//返回通知
//    @AfterReturning(value = "execution(public float aspectj.SmartDog.getSum(float, float))", returning = "res")@AfterReturning(value = "mypointcut()",returning = "res")public void showSuccessEndLog(JoinPoint joinPoint, Object res) {Signature signature = joinPoint.getSignature();System.out.println("1返回通知" + signature.getName() + " 返回的结果是=" + res);}//异常通知
//    @AfterThrowing(value = "execution(public float aspectj.SmartDog.getSum(float, float))", throwing = "throwable")@AfterThrowing(value = "mypointcut()",throwing = "throwable")public void showExceptionLog(JoinPoint joinPoint, Throwable throwable) {Signature signature = joinPoint.getSignature();System.out.println("1异常通知" + signature.getName() + " 异常信息=" + throwable);}//最终通知
//    @After(value = "execution(public float aspectj.SmartDog.getSum(float, float))")@After(value = "mypointcut()")public void showFinallyEndLog(JoinPoint joinPoint) {Signature signature = joinPoint.getSignature();System.out.println("1最终通知" + signature.getName());}}

切面类2(没有切面类1的优先级高)

package aspectj;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;import java.util.Arrays;/*** @version 1.0* 这是一个切面类*/
@Order(value = 2)
@Aspect
@Component("smartAnimalAspect2")
public class SmartAnimalAspect2 {//    切入表达式重用技术@Pointcut(value = "execution(public float aspectj.SmartDog.getSum(float, float))")public void mypointcut(){}//前置通知
//    @Before(value = "execution(public float aspectj.SmartDog.getSum(float, float))")@Before(value = "mypointcut()")public void showBeginLog(JoinPoint joinPoint) {//通过连接点对象joinPoint 可以获取方法签名Signature signature = joinPoint.getSignature();System.out.println("2前置通知");}//返回通知
//    @AfterReturning(value = "execution(public float aspectj.SmartDog.getSum(float, float))", returning = "res")@AfterReturning(value = "mypointcut()",returning = "res")public void showSuccessEndLog(JoinPoint joinPoint, Object res) {Signature signature = joinPoint.getSignature();System.out.println( "2返回通知 返回的结果是=" + res);}//异常通知
//    @AfterThrowing(value = "execution(public float aspectj.SmartDog.getSum(float, float))", throwing = "throwable")@AfterThrowing(value = "mypointcut()",throwing = "throwable")public void showExceptionLog(JoinPoint joinPoint, Throwable throwable) {Signature signature = joinPoint.getSignature();System.out.println("2异常通知" + throwable);}//最终通知
//    @After(value = "execution(public float aspectj.SmartDog.getSum(float, float))")@After(value = "mypointcut()")public void showFinallyEndLog(JoinPoint joinPoint) {Signature signature = joinPoint.getSignature();System.out.println("2最终通知" + signature.getName());}}

结果: 

 

注意 

不能理解成:优先级高的每个消息通知都先执行,这个和方法调用机制(和 Filter 过滤器
链式调用类似)

8.基于XML的AOP

定义SmartAnimalable接口

package xml;/*** @author ygd*/
public interface SmartAnimalable {float getSum(float i, float j);float getSub(float i, float j);
}

定义SmartDog类

package xml;/*** @author ygd*/
public class SmartDog implements SmartAnimalable {@Overridepublic float getSum(float i, float j) {float result = i + j;System.out.println("getSum() 方法内部打印 result= " + result);return result;}@Overridepublic float getSub(float i, float j) {float result = i - j;System.out.println("getSub() 方法内部打印 result= " + result);return result;}
}

定义SmartAnimalAspect切面类

package xml;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;import java.util.Arrays;/*** @version 1.0* 这是一个基于XML的切面类*/public class SmartAnimalAspect {public void showBeginLog(JoinPoint joinPoint) {//通过连接点对象joinPoint 可以获取方法签名Signature signature = joinPoint.getSignature();System.out.println("1前置通知" + signature.getName() + "-参数 "+ Arrays.asList(joinPoint.getArgs()));}public void showSuccessEndLog(JoinPoint joinPoint, Object res) {Signature signature = joinPoint.getSignature();System.out.println("1返回通知" + signature.getName() + " 返回的结果是=" + res);}public void showExceptionLog(JoinPoint joinPoint, Throwable throwable) {Signature signature = joinPoint.getSignature();System.out.println("1异常通知" + signature.getName() + " 异常信息=" + throwable);}public void showFinallyEndLog(JoinPoint joinPoint) {Signature signature = joinPoint.getSignature();System.out.println("1最终通知" + signature.getName());}}

定义beans01.xml

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"><!--配置一个切面类对象-bean--><bean class="xml.SmartAnimalAspect" id="smartAnimalAspect"/>
<!--配置SmartDog对象-bean--><bean class="xml.SmartDog" id="dog"/>
<!--配置切面类,一定要引入xmlns:aop命名空间--><aop:config>
<!-- 注意顺序,先配置切入点,在配置切面对象-->
<!--配置切入点--><aop:pointcut id="mypointcut" expression="execution(public float xml.SmartDog.getSum(float, float))"/>
<!--这里指定切面对象--><aop:aspect ref="smartAnimalAspect" order="10">
<!--配置前置通知--><aop:before method="showBeginLog" pointcut-ref="mypointcut"/>
<!--配置返回通知--><aop:after-returning method="showSuccessEndLog" pointcut-ref="mypointcut" returning="res"/>
<!--配置异常通知--><aop:after-throwing method="showExceptionLog" pointcut-ref="mypointcut" throwing="throwable"/>
<!--配置最终通知--><aop:after method="showFinallyEndLog" pointcut-ref="mypointcut"/></aop:aspect></aop:config></beans>

注意点:要 先配置切面点,在配置切面类

xml的语法,跟上面所写的基于注解的aop道理都是一样的。

9.Spring的AOP机制是基于Spring框架中的基于JDK的动态代理和基于CGLib的动态代理

动态代理 基于jdk的Proxy(面向接口) 与spring的CGlib(面向父类)-CSDN博客

相关文章:

Spring AOP技术

1.AOP基本介绍 AOP 的全称 (aspect oriented programming) &#xff0c;面向切面编程。 1.和传统的面向对象不同。 面向切面编程是根据自我的需求&#xff0c;将切面类的方法切入到其他的类的方法中。&#xff08;这么说抽象吧&#xff01;来张图来解释。&#xff09; 如图 传…...

数字IC实践项目(10)—基于System Verilog的DDR4 Model/Tb 及基础Verification IP的设计与验证(付费项目)

数字IC实践项目&#xff08;10&#xff09;—基于System Verilog的DDR4 Model/Tb 及基础Verification IP的设计与验证&#xff08;付费项目&#xff09; 前言项目框图1&#xff09;DDR4 Verification IP2&#xff09;DDR4 JEDEC Model & Tb 项目文件1&#xff09;DDR4 Veri…...

MATLAB保存多帧图形为视频格式

基本思路 在Matlab中&#xff0c;要将drawnow绘制的多帧数据保存为视频格式&#xff0c;首先需要创建一个视频写入对象。这个对象用于将每一帧图像数据按照视频格式的要求进行组合和编码。然后&#xff0c;在每次drawnow更新绘图后&#xff0c;将当前的图形窗口内容捕获为一帧图…...

redis7.x源码分析:(3) dict字典

dict字典采用经典hash表数据结构实现&#xff0c;由键值对组成&#xff0c;类似于C中的unordered_map。两者在代码实现层面存在一些差异&#xff0c;比如gnustl的unordered_map分配的桶数组个数是&#xff08;质数n&#xff09;&#xff0c;而dict分配的桶数组个数是&#xff0…...

连续九届EI稳定|江苏科技大学主办

【九届EI检索稳定|江苏科技大学主办 | IEEE出版 】 &#x1f388;【截稿倒计时】&#xff01;&#xff01;&#xff01; ✨徐秘书&#xff1a;gsra_huang ✨往届均已检索&#xff0c;已上线IEEE官网 &#x1f38a;第九届清洁能源与发电技术国际学术会议&#xff08;CEPGT 2…...

HarmonyOS NEXT应用开发实战 ( 应用的签名、打包上架,各种证书详解)

前言 没经历过的童鞋&#xff0c;首次对HarmonyOS的应用签名打包上架可能感觉繁琐。需要各种秘钥证书生成和申请&#xff0c;混在一起也分不清。其实搞清楚后也就那会事&#xff0c;各个文件都有它存在的作用。 HarmonyOS通过数字证书与Profile文件等签名信息来保证鸿蒙应用/…...

【CICD】CICD 持续集成与持续交付在测试中的应用

一、什么是CICD&#xff1f; CI/CD 是指持续集成&#xff08;Continuous Integration&#xff09;和持续部署&#xff08;Continuous Deployment&#xff09;或持续交付&#xff08;Continuous Delivery&#xff09; 1.1 持续集成&#xff08;Continuous Integration&#xf…...

Dolby TrueHD和Dolby Digital Plus (E-AC-3)编码介绍

文章目录 1. Dolby TrueHD特点总结 2. Dolby Digital Plus (E-AC-3)特点总结 Dolby TrueHD 与 Dolby Digital Plus (E-AC-3) 的对比 Dolby TrueHD和Dolby Digital Plus (E-AC-3) 是两种高级的杜比音频编码格式&#xff0c;常用于蓝光影碟、流媒体、影院等高品质音频传输场景。它…...

数字频率计的设计-- 基于 HDL 方法

目录 数字频率计的设计 1.计数、锁存与显示译码电路设计 2.主控电路设计 3.分频电路设计 4.顶层电路设计 伪随机序列发生器 的设计 数字频率计的设计 基于HDL设计数字系统时&#xff0c;可以根据需要应用Verilog HDL描述所需要的功能电路&#xff0c;既有利于节约资源&am…...

[程序员] 没有产生core文件的原因

最近和同事一块看一个core文件没有产生的问题,总结了一些在CSDN的专栏里。分析的过程,参考使用了ftrace的功能,感觉非常实用。 如果有需要可以参考。大体上就这么几种情况:信号的特殊处理,coredump相关的配置没有设置正确,文件系统访问权限问题,setuid相关的不匹配问题。…...

【数字图像处理+MATLAB】基于 Sobel 算子计算图像梯度并进行边缘增强:使用 imgradientxy 函数

引言 在图像处理中&#xff0c;边缘通常是图像中像素强度变化最大的地方&#xff0c;这种变化可以通过计算图像的梯度来量化。梯度是一个向量&#xff0c;它的方向指向像素强度增加最快的方向&#xff0c;它的大小&#xff08;或者说幅度&#xff09;表示像素强度增加的速度。…...

P10901 [蓝桥杯 2024 省 C] 封闭图形个数

铁子们好呀&#xff0c;今天博主给大家更新一道编程题&#xff01;&#xff01;&#xff01; 题目链接如下&#xff1a; P10901 [蓝桥杯 2024 省 C] 封闭图形个数 好&#xff0c;接下来&#xff0c;我将从三个方面讲解这道例题。分别是 题目解析算法原理代码实现 文章目录 1.题…...

ubuntu-desktop-24.04上手指南(更新阿里源、安装ssh、安装chrome、设置固定IP、安装搜狗输入法)

ubuntu-desktop-24.04上手指南(更新阿里源、安装ssh、安装chrome、设置固定IP、安装搜狗输入法) 一、更新并安装基础软件 #切换root用户 sudo su -#更新 apt update #升级 apt upgrade#install vim apt install vim#install net-tools apt install net-tools二、安装ssh并设置…...

手机直连卫星NTN通信初步研究

目录 1、手机直连卫星之序幕 2、卫星NTN及其网络架构 2.1 NTN 2.2 NTN网络架构 3、NTN的3GPP标准化进程 3.1 NTN需要适应的特性 3.2 NTN频段 3.3 NTN的3GPP标准化进程概况 3.4 NTN的3GPP标准化进程的详情 3.4.1 NR-NTN 3.4.1.1 NTN 的无线相关 SI/WI 3.4.1.2…...

蓝桥杯c++算法学习【2】之搜索与查找(九宫格、穿越雷区、迷宫与陷阱、扫地机器人:::非常典型的必刷例题!!!)

别忘了请点个赞收藏关注支持一下博主喵&#xff01;&#xff01;&#xff01; 关注博主&#xff0c;更多蓝桥杯nice题目静待更新:) 搜索与查找 一、九宫格 【问题描述】 小明最近在教邻居家的小朋友小学奥数&#xff0c;而最近正好讲述到了三阶幻方这个部分&#xff0c;三 …...

Android加载pdf

依赖 implementation com.squareup.okhttp3:okhttp:4.9.1 implementation com.github.barteksc:android-pdf-viewer:3.2.0-beta.1在project.build中添加该源 maven { url "https://repository.liferay.com/nexus/content/repositories/public/" }XML <LinearLa…...

IOT物联网低代码可视化大屏解决方案汇总

目录 参考来源云服务商阿里云物联网平台产品主页产品文档 开源项目DGIOT | 轻量级工业物联网开源平台项目特点项目地址开源许可 IoTGateway | 基于.NET6的跨平台工业物联网网关项目特点项目地址开源许可 IoTSharp | 基于.Net Core开源的物联网基础平台项目特点项目地址开源许可…...

Python的面向对象day7

1、什么是面向对象 面向对象称为OO&#xff0c;他通过将数据和功能封装在一个被称为‘对象’的实体中&#xff0c;来组织和管理代码。面向对象变成&#xff08;OOP&#xff09;具有四个特性&#xff0c;封装、继承、多态、抽象 优点&#xff1a;模块化、安全性高、代码重用性…...

计算机网络(11)和流量控制补充

这一篇对数据链路层中的和流量控制进行详细学习 流量控制&#xff08;Flow Control&#xff09;是计算机网络中确保数据流平稳传输的技术&#xff0c;旨在防止数据发送方发送过多数据&#xff0c;导致接收方的缓冲区溢出&#xff0c;进而造成数据丢失或传输失败。流量控制通常…...

Rust 所有权机制

Rust 所有权机制 本文示例代码地址 所有权是Rust中最独特的特性&#xff0c;它让Rust无需GC就可以保证内存安全。 什么是所有权&#xff1f; 所有权&#xff08;ownership&#xff09;是 Rust 用于如何管理内存的一组规则。所有程序都必须管理其运行时使用计算机内存的方式…...

Leetcode 3576. Transform Array to All Equal Elements

Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接&#xff1a;3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到&#xf…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!

5月28日&#xff0c;中天合创屋面分布式光伏发电项目顺利并网发电&#xff0c;该项目位于内蒙古自治区鄂尔多斯市乌审旗&#xff0c;项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站&#xff0c;总装机容量为9.96MWp。 项目投运后&#xff0c;每年可节约标煤3670…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现

摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序&#xff0c;以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务&#xff0c;提供稳定高效的数据处理与业务逻辑支持&#xff1b;利用 uniapp 实现跨平台前…...

LLM基础1_语言模型如何处理文本

基于GitHub项目&#xff1a;https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken&#xff1a;OpenAI开发的专业"分词器" torch&#xff1a;Facebook开发的强力计算引擎&#xff0c;相当于超级计算器 理解词嵌入&#xff1a;给词语画"…...

vue3+vite项目中使用.env文件环境变量方法

vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量&#xff0c;这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问&#xff08;基础概念问题&#xff09; 1. 请解释Spring框架的核心容器是什么&#xff1f;它在Spring中起到什么作用&#xff1f; Spring框架的核心容器是IoC容器&#…...

【Go语言基础【12】】指针:声明、取地址、解引用

文章目录 零、概述&#xff1a;指针 vs. 引用&#xff08;类比其他语言&#xff09;一、指针基础概念二、指针声明与初始化三、指针操作符1. &&#xff1a;取地址&#xff08;拿到内存地址&#xff09;2. *&#xff1a;解引用&#xff08;拿到值&#xff09; 四、空指针&am…...

Web后端基础(基础知识)

BS架构&#xff1a;Browser/Server&#xff0c;浏览器/服务器架构模式。客户端只需要浏览器&#xff0c;应用程序的逻辑和数据都存储在服务端。 优点&#xff1a;维护方便缺点&#xff1a;体验一般 CS架构&#xff1a;Client/Server&#xff0c;客户端/服务器架构模式。需要单独…...

Chrome 浏览器前端与客户端双向通信实战

Chrome 前端&#xff08;即页面 JS / Web UI&#xff09;与客户端&#xff08;C 后端&#xff09;的交互机制&#xff0c;是 Chromium 架构中非常核心的一环。下面我将按常见场景&#xff0c;从通道、流程、技术栈几个角度做一套完整的分析&#xff0c;特别适合你这种在分析和改…...

tauri项目,如何在rust端读取电脑环境变量

如果想在前端通过调用来获取环境变量的值&#xff0c;可以通过标准的依赖&#xff1a; std::env::var(name).ok() 想在前端通过调用来获取&#xff0c;可以写一个command函数&#xff1a; #[tauri::command] pub fn get_env_var(name: String) -> Result<String, Stri…...