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

Spring核心思想之—AOP(面向切面编程)

目录

一 .AOP概述

 二. Spring AOP 使用

 2.1 引入AOP依赖

2.2 编写AOP程序 

 三. Spring AOP详情

3.1 切点(Pointcut)

3.2 连接点(Join Point)

3.3通知(Advice)

3.4切面(Aspect)

3.5通知

3.6 @PointCut (公共切点)

3.7 切面类的优先级 @Order

 3.8 切点表达式

 3.8.1 execution表达式

3.8.2@annotation 

 四 代理模式

 总结:


一 .AOP概述

        Spring 两大核心思想:

  •                IoC :IoC概述(详情)
  •                AOP:Aspect Oriented Programming (面向切面编程)

什么是切面编程呢? 切面编程指的是某一类特定问题  所以AOP也可以理解为面向特定方法编程。

什么是面向特定方法编程呢?统一功能处理之拦截器、统一数据返回格式、统一异常处理 这类的问题的统一处理, 所以拦截器也是AOP的一种应用, AOP是一种思想, 拦截器就是AOP思想的一种实现,. Spring框架实现了这种思想, 提供了拦截器技术的相关接⼝。

同样统一数据返回格式、统一异常处理 都是AOP思想的一种实现。

可以这么理解 AOP是一种思想 , 是对某一类事物的集中处理

        例如上面的 统一功能处理之拦截器、统一数据返回格式、统一异常处理

 二. Spring AOP 使用

 2.1 引入AOP依赖

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

2.2 编写AOP程序 

创建编写切面类:

@Slf4j
@Component
@Aspect
public class AspectDemo {//定义切点(公共的切点表达式)@Pointcut("execution(* com.example.springaop.controller.*.*(..))")public void pointcut(){};@Around("pointcut()")public Object test2(ProceedingJoinPoint joinPoint) throws Throwable {log.info("环绕通知  方法前执行....");Object result = joinPoint.proceed();log.info("环绕通知  方法后执行....");return result;}/*** @param joinPoint* @return 针对使用@MyAspect注解的方法* @throws Throwable*/@Around("@annotation(com.example.springaop.config.MyAspect)")public Object test(ProceedingJoinPoint joinPoint) throws Throwable {log.info("环绕通知  方法前执行....");Object result = joinPoint.proceed();log.info("环绕通知  方法后执行....");return result;}/**** @param joinPoint* @return  针对使用@RequestMapping注解的方法* @throws Throwable*/@Around("@annotation(org.springframework.web.bind.annotation.RequestMapping)")public Object test1(ProceedingJoinPoint joinPoint) throws Throwable {log.info("环绕通知  方法前执行....");Object result = joinPoint.proceed();log.info("环绕通知  方法后执行....");return result;}
}

启动类conterllor 类代码 如下: 

@RequestMapping("/user")
@RestController
@Slf4j
public class UserController {@MyAspect@RequestMapping("/user")public void text01(){log.info("我是text01");}@RequestMapping("/getUser1")public boolean text02(){int a = 10/0;return true;}
}
对程序进⾏简单的讲解:
@Aspect:标识这是个切面类
@Around:环绕通知, 在方法前后都会执行, 后面参数表示对那些方法生效
@ProceedingJoinPoint.proceed() 让原始⽅法执⾏

AOP 面向切面编程优点:

  • 代码无侵入:不用修改原始方法, 就可以对方法进行增强或者功能的变更
  • 减少重复代码
  • 提高开发效率
  • 维护方便 

 三. Spring AOP详情

3.1 切点(Pointcut)

Pointcutz作用:告诉程序对 哪些⽅法来进⾏功能增强.也称:公共切点表达式!

3.2 连接点(Join Point

满⾜切点表达式规则的⽅法, 就是连接点. 也就是可以被AOP控制的⽅法
所有 com.example.springaop.controller 路径下的⽅法, 都是连接点.
切点和连接点的关系
连接点是满⾜切点表达式的元素. 切点可以看做是保存了众多连接点的⼀个集合.

3.3通知(Advice)

通知就是具体要做的⼯作, 指哪些重复的逻辑,也就是共性功能(最终体现为⼀个⽅法)

在AOP⾯向切⾯编程当中, 我们把这部分重复的代码逻辑抽取出来单独定义, 这部分代码就是通知的内 容 

3.4切面(Aspect)

 切⾯(Aspect) = 切点(Pointcut) + 通知(Advice)

切⾯所在的类, 我们⼀般称为切⾯类(被@Aspect注解标识的类) 

3.5通知

Spring中AOP的通知类型有以下几种:

  • @Around:环绕通知,此注解标注的通知方法在目标方法前,后都被执行
  • @Before:前置通知,此注解标注的通知方法在目标方法前被执行
  • @After:后置通知,此注解标注的通知方法在目标方法后被执行,无论是否有异常都会执行
  • @AfterReturning:返回后通知,此注解标注的通知方法在目标方法后被执行,有异常不会执行
  • @AfterThrowing:异常后通知,此注解标注的通知方法发生异常后执行

@Slf4j
@Aspect
@Component
public class AspectDemo {//前置通知@Before("execution(* com.example.springaop.controller.*.*(..))")public void doBefore() {log.info("执⾏ Before ⽅法");}//后置通知@After("execution(* com.example.springaop.controller.*.*(..))")public void doAfter() {log.info("执⾏ After ⽅法");}//返回后通知@AfterReturning("execution(* com.example.springaop.controller.*.*(..))")public void doAfterReturning() {log.info("执⾏ AfterReturning ⽅法");}//抛出异常后通知@AfterThrowing("execution(* com.example.springaop.controller.*.*(..))")public void doAfterThrowing() {log.info("执⾏ doAfterThrowing ⽅法");}//添加环绕通知@Around("execution(* com.example.springaop.controller.*.*(..))")public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {log.info("Around ⽅法开始执⾏");Object result = joinPoint.proceed();log.info("Around ⽅法结束执⾏");return result;}
}

测试启动类:

@RequestMapping("/user")
@RestController
public class UserController {private static final Logger log = LoggerFactory.getLogger(UserController.class);@MyAspect@RequestMapping("/user")public void text01(){log.info("我是text01");}@RequestMapping("/getUser1")public boolean text02(){int a = 10/0;return true;}
}

 测试运行正常的结果:

程序正常运⾏的情况下, @AfterThrowing 标识的通知⽅法不会执⾏
从上图也可以看出来, @Around 标识的通知⽅法包含两部分, ⼀个"前置逻辑", ⼀个"后置逻辑".其 中"前置逻辑" 会先于 @Before 标识的通知⽅法执⾏, "后置逻辑" 会晚于 @After 标识的通知⽅法执⾏
测试结果流程图:

测试运行报错的异常的情况: 

程序发⽣异常的情况下:
  • @AfterReturning 标识的通知⽅法不会执⾏, @AfterThrowing 标识的通知⽅法执⾏了
  • @Around 环绕通知中原始⽅法调⽤时有异常,通知中的环绕后的代码逻辑也不会在执⾏了(因为 原始⽅法调⽤出异常了)

 测试结果流程图:

 注意 :

  • @Around 环绕通知需要调⽤ ProceedingJoinPoint.proceed() 来让原始⽅法执⾏, 其他 通知不需要考虑⽬标⽅法执⾏.
  • @Around 环绕通知⽅法的返回值, 必须指定为Object, 来接收原始⽅法的返回值, 否则原始⽅法执 ⾏完毕, 是获取不到返回值的.
  • ⼀个切⾯类可以有多个切点.

3.6 @PointCut (公共切点)

Spring 提供了 @PointCut 注解,
把公共的切点表达式提取出来,需要用到时引用该切入点表达式即可,便于后续代码的维护。

//公共切点@Pointcut("execution(* com.example.springaop.controller.*.*(..))")public void pointCut() {};//前置通知@Before("pointCut()")public void doBefore() {log.info("执⾏ Before ⽅法");}

3.7 切面类的优先级 @Order

 没有使用 @Order时 多个切面类同时启动的结果:

存在多个切⾯类时, 默认按照切⾯类的类名字⺟排序:
  • @Before 通知:字⺟排名靠前的先执⾏
  • @After 通知:字⺟排名靠前的后执⾏

 使用 @Order时 多个切面类同时启动的结果:

通过上述程序的运⾏结果, 得出结论:
@Order 注解标识的切⾯类, 执⾏顺序如下:
  • @Before 通知:数字越⼩先执⾏
  • @After 通知:数字越⼤先执⾏

 3.8 切点表达式

切点表达式常⻅有两种表达⽅式
  • execution(...):根据⽅法的签名来匹配
  • @annotation(....) :根据注解匹配

 3.8.1 execution表达式

匹配语法为:

              execution ( <访问修饰符>  <返回类型>  <包名.类名.⽅法(⽅法参数)>  <异常>)

3.8.2@annotation 

execution表达式更适⽤有规则的, 如果我们要匹配多个⽆规则的⽅法呢, 


:如果我们 匹配两个不同类的一个方法,怎么操作呢?
我们可以借助⾃定义注解的⽅式以及另⼀种切点表达式 @annotation 来描述这⼀类的切点
 

 实现步骤:

  1. 编写自定义类
  2. 使用@annotation 表达式来描述切点
  3. 在连接点的方法上添加自定义注解 

 第一步:首先创建一个自定义类 MyAspect

 具体代码

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAspect {}

注解解释:

一.@Target 标识了 Annotation 所修饰的对象范围, 即该注解可以⽤在什么地⽅. 常⽤取值:

  • ElementType.TYPE: ⽤于描述类、接⼝(包括注解类型) 或enum声明
  • ElementType.METHOD: 描述⽅法
  • ElementType.PARAMETER: 描述参数
  • ElementType.TYPE_USE: 可以标注任意类型

二. @Retention 指Annotation被保留的时间⻓短, 标明注解的⽣命周期,@Retention 的取值有三种:

  • RetentionPolicy.SOURCE:表⽰注解仅存在于源代码中, 编译成字节码后会被丢弃. 这意味着在运⾏时⽆法获取到该注解的信息, 只能在编译时使⽤. ⽐如 @SuppressWarnings , 以及 lombok提供的注解 @Data , @Slf4j
  • RetentionPolicy.CLASS:编译时注解. 表⽰注解存在于源代码和字节码中, 但在运⾏时会被丢弃. 这意味着在编译时和字节码中可以通过反射获取到该注解的信息, 但在实际运⾏时⽆法获 取. 通常⽤于⼀些框架和⼯具的注解.
  • RetentionPolicy.RUNTIME:运⾏时注解. 表⽰注解存在于源代码, 字节码和运⾏时中. 这意味着在编译时, 字节码中和实际运⾏时都可以通过反射获取到该注解的信息. 通常⽤于⼀些需要 在运⾏时处理的注解, 如Spring的 @Controller @ResponseBody

 第二步:在切面类中使用@annotation

@Slf4j
@Aspect
@Component
@Order(3)
public class ApectDemo2 {@After("@annotation(com.example.springaop.config.MyAspect)")public void doAfter() {log.info("ApectDemo2 执⾏ After ⽅法");}
}

@annotationh后面的连接点就是 自定义注解类的路径

第三步:在 需要执行的方法上面加上 自定义注解 @MyAspect:

@RequestMapping("/user")
@RestController
@Slf4j
public class UserController {@MyAspect@RequestMapping("/user")public void text01(){log.info("我是text01");}
}

Spring AOP 的实现方式 (常见面试题):

  1. 基于注解 @Aspect。
  2. 基于自定义注解(@annotation)。
  3. 基于 Spring API(通过 xml 配置的方式,自从 SpringBoot 广泛使用之后,这种方法几乎看不到了)。
  4. 基于代理来实现(更加久远的一种实现方式,写法笨重,不建议使用)

 四 代理模式

        Spring AOP 是基于动态代理来实现 AOP 的

 其代理模式 也称委托模式

定义:为其他对象提供⼀种代理以控制对这个对象的访问. 它的作⽤就是通过提供⼀个代理类, 让我们
在调⽤⽬标⽅法的时候, 不再是直接对⽬标⽅法进⾏调⽤, ⽽是通过代理类间接调⽤.
在某些情况下, ⼀个对象不适合或者不能直接引⽤另⼀个对象, ⽽代理对象可以在客⼾端和⽬标对象之
间起到中介的作⽤.

 代理模式可以在不修改被代理对象的基础上, 通过扩展代理类, 进⾏⼀些功能的附加与增强.

根据代理的创建时期,代理模式分为静态代理动态代理

  • 静态代理:由程序员创建代理类或特定工具自动生成源代码再对其编译,在程序运行前代理类的 .class 文件就已经存在了。
  • 动态代理:在程序运行时,运用反射机制动态创建而成

 总结:

  1. AOP是⼀种思想, 是对某⼀类事情的集中处理. Spring框架实现了AOP, 称之为SpringAOP
  2. Spring AOP常⻅实现⽅式有两种: 1. 基于注解@Aspect来实现 2. 基于⾃定义注解来实现, 还有⼀些 更原始的⽅式,⽐如基于代理, 基于xml配置的⽅式, 但⽬标⽐较少⻅
  3.  Spring AOP 是基于动态代理实现的, 有两种⽅式: 1. 基本JDK动态代理实现 2. 基于CGLIB动态代理 实现. 运⾏时使⽤哪种⽅式与项⽬配置和代理的对象有关

相关文章:

Spring核心思想之—AOP(面向切面编程)

目录 一 .AOP概述 二. Spring AOP 使用 2.1 引入AOP依赖 2.2 编写AOP程序 三. Spring AOP详情 3.1 切点(Pointcut) 3.2 连接点(Join Point&#xff09; 3.3通知&#xff08;Advice&#xff09; 3.4切面(Aspect) 3.5通知 3.6 PointCut &#xff08;公共切点&#xff09;…...

使用 Openpyxl 操作 Excel 文件详解

文章目录 安装安装Python3安装 openpyxl 基础操作1. 引入2. 创建工作簿和工作表3. 写入数据4. 保存工作簿5. 加载已存在的Excel6. 读取单元格的值7. 选择工作表 样式和格式化1. 引入2. 设置字体3. 设置边框4. 填充5. 设置数字格式6. 数据验证7. 公式操作 性能优化1. read_only/…...

关于使用雪花算法生成唯一ID,返回给前端ID不一致的问题

问题 在某个项目中,使用雪花算法生成的唯一ID,从数据库查询到数据后返回给前端,但是前端接受到的数据ID和数据库原先生成的不一致 但是前端展示的数据: 原因 原因是后端使用Long类型来存储雪花算法生成的ID,但是这个数值已经超过前端数值类型的范围,导致前端在存储这个数值…...

axios post请求 接收sse[eventsource]数据的

axios 接收sse数据的 axios 接收sse数据的 EventSource什么 基于 HTTP 协议实现&#xff0c;通过与服务器建立一个持续连接&#xff0c;实现了服务器向客户端推送事件数据的功能。在客户端&#xff0c;EventSource 对象通过一个 URL 发起与服务器的连接。连接成功后&#xff0…...

Spring Boot 示例项目:从零开始构建 Web 应用

一、项目概述 本文档将指导您通过一个示例项目,了解如何使用 Spring Boot 框架构建一个简单的 Web 应用程序。该项目涵盖了从数据模型定义到控制器、服务层以及数据访问层的完整开发流程,帮助您快速掌握 Spring Boot 的基本使用方法。 二、项目结构 1. 项目模块 本示例项…...

大语言模型常用微调与基于SFT微调DeepSeek R1指南

概述 大型语言模型&#xff08;LLM&#xff0c;Large Language Model&#xff09;的微调&#xff08;Fine-tuning&#xff09;是指在一个预训练模型的基础上&#xff0c;使用特定领域或任务的数据对模型进行进一步训练&#xff0c;以使其在该领域或任务上表现更好。微调是迁移…...

聚焦地灾防治,助力城市地质安全风险防控

城市是人类社会发展的重要载体&#xff0c;承载着经济繁荣、文化交流和人口聚集等重要功能。然而&#xff0c;由于城市建设过程中地质条件复杂&#xff0c;地质灾害风险隐患存在&#xff0c;城市地质安全等问题日益突出&#xff0c;引起人们的广泛关注。为保障城市发展的安全和…...

为什么WP建站更适合于谷歌SEO优化?

在当今数字时代&#xff0c;建立一个网站似乎变得容易&#xff0c;但要构建一个真正能够带来流量和订单的网站却并非易事。特别是在谷歌SEO优化方面&#xff0c;不同的建站程序在SEO支持方面的效果差异显著。对于希望提升搜索引擎表现的用户来说&#xff0c;WordPress无疑是最佳…...

基于JavaScript的实时数据监控仪表盘开发实践

基于JavaScript的实时数据监控仪表盘开发实践 一、项目背景 某云计算服务商需要为其客户提供服务器集群健康状态监控系统。原有系统存在以下痛点&#xff1a; 数据刷新依赖手动操作可视化效果单一&#xff08;仅表格展示&#xff09;缺乏异常状态的智能预警移动端适配性差 …...

同步异步日志系统-日志落地模块的实现

功能&#xff1a;将格式化完成后的日志消息字符串&#xff0c;输出到指定的位置 扩展&#xff1a;支持同时将日志落地到不同的位置 位置分类&#xff1a; 1.标准输出 2.指定文件&#xff08;时候进行日志分析&#xff09; 3.滚动文件&#xff08;文件按照时间/大小进行滚动…...

大模型常识:什么是大模型/大语言模型/LLM

本文原创作者:姚瑞南 AI-agent 大模型运营专家,先后任职于美团、猎聘等中大厂AI训练专家和智能运营专家岗;多年人工智能行业智能产品运营及大模型落地经验,拥有AI外呼方向国家专利与PMP项目管理证书。(转载需经授权) 目录 一、什么是语言模型? 那么什么是语言模…...

用deepseek学大模型08-长短时记忆网络 (LSTM)

deepseek.com 从入门到精通长短时记忆网络(LSTM),着重介绍的目标函数&#xff0c;损失函数&#xff0c;梯度下降 标量和矩阵形式的数学推导&#xff0c;pytorch真实能跑的代码案例以及模型,数据&#xff0c; 模型应用场景和优缺点&#xff0c;及如何改进解决及改进方法数据推导…...

IOT通道MQTT

IoT通道是物联网&#xff08;IoT&#xff09;系统中用于设备与云端或设备之间通信的专用通道&#xff0c;其主要作用是实现数据的高效传输和设备的远程控制。以下是关于IoT通道的定义、应用和技术特点的总结&#xff1a; 定义 IoT通道是物联网设备与云端或设备之间建立的通信…...

(蓝桥杯——10. 小郑做志愿者)洛斯里克城志愿者问题详解

题目背景 小郑是一名大学生,她决定通过做志愿者来增加自己的综合分。她的任务是帮助游客解决交通困难的问题。洛斯里克城是一个六朝古都,拥有 N 个区域和古老的地铁系统。地铁线路覆盖了树形结构上的某些路径,游客会询问两个区域是否可以通过某条地铁线路直达,以及有多少条…...

小胡说技书博客分类(部分目录):服务治理、数据治理与安全治理对比表格

文章目录 一、对比表格二、目录2.1 服务2.2 数据2.3 安全 一、对比表格 下表从多个维度对服务治理、数据治理和安全治理进行详细对比&#xff0c;为读者提供一个直观而全面的参考框架。 维度服务治理数据治理安全治理定义对软件开发全流程、应用交付及API和接口管理进行规范化…...

开源模型应用落地-DeepSeek-R1-Distill-Qwen-7B-LoRA微调-LLaMA-Factory-单机单卡-V100(一)

一、前言 如今&#xff0c;大语言模型领域热闹非凡&#xff0c;各种模型不断涌现。DeepSeek-R1-Distill-Qwen-7B 模型凭借其出色的效果和性能&#xff0c;吸引了众多开发者的目光。而 LLaMa-Factory 作为强大的微调工具&#xff0c;能让模型更好地满足个性化需求。 在本篇中&am…...

如何避免redis长期运行持久化AOF文件过大的问题:AOF重写

一、AOF 重写的核心作用 通过 重建 AOF 文件&#xff0c;解决以下问题&#xff1a; 体积压缩&#xff1a;消除冗余命令&#xff08;如多次修改同一 key&#xff09;&#xff0c;生成最小操作集合。混合持久化支持&#xff08;若启用 aof-use-rdb-preamble yes&#xff09;&am…...

uni-app发起网络请求的三种方式

uni.request(OBJECT) 发起网络请求 具体参数可查看官方文档uni-app data:请求的参数; header&#xff1a;设置请求的 header&#xff0c;header 中不能设置 Referer&#xff1b; method&#xff1a;请求方法&#xff1b; timeout&#xff1a;超时时间&#xff0c;单位 ms&a…...

以下是一个使用 HTML、CSS 和 JavaScript 实现的登录弹窗效果示例

以下是一个使用 HTML、CSS 和 JavaScript 实现的登录弹窗效果示例&#xff1a; <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><title>登录弹窗示例</title><style>body {font-family: Aria…...

EasyRTC:智能硬件适配,实现多端音视频互动新突破

一、智能硬件全面支持&#xff0c;轻松跨越平台障碍 EasyRTC 采用前沿的智能硬件适配技术&#xff0c;无缝对接 Windows、macOS、Linux、Android、iOS 等主流操作系统&#xff0c;并全面拥抱 WebRTC 标准。这一特性确保了“一次开发&#xff0c;多端运行”的便捷性&#xff0c…...

LeetCode1287

LeetCode1287 目录 题目描述示例思路分析代码段代码逐行讲解复杂度分析总结的知识点整合总结 题目描述 给定一个非递减的整数数组 arr&#xff0c;其中有一个元素恰好出现超过数组长度的 25%。请你找到并返回这个元素。 示例 示例 1 输入: arr [1, 2, 2, 6, 6, 6, 6, 7,…...

【计算机网络】网络层数据包(Packet)格式

在计算机网络中&#xff0c;数据包&#xff08;Packet&#xff09; 是网络层的协议数据单元&#xff08;PDU&#xff09;&#xff0c;用于在不同网络之间传输数据。数据包的格式取决于具体的网络层协议&#xff08;如 IPv4、IPv6 等&#xff09;。以下是常见数据包格式的详细说…...

使用vite打包并部署vue项目到nginx

1 使用 Vite 创建 vue3 项目 Vite 是一个新型的前端构建工具&#xff0c;专为现代浏览器和工具链而设计&#xff0c;提供了极快的冷启动和热模块更新&#xff08;HMR&#xff09;速度。以下是使用 Vite 创建 Vue 3 项目的详细步骤&#xff1a; 一、安装 Node.js 和 npm 首先…...

深度学习笔记之自然语言处理(NLP)

深度学习笔记之自然语言处理(NLP) 在行将开学之时&#xff0c;我将开始我的深度学习笔记的自然语言处理部分&#xff0c;这部分内容是在前面基础上开展学习的&#xff0c;且目前我的学习更加倾向于通识。自然语言处理部分将包含《动手学深度学习》这本书的第十四章&#xff0c…...

【ISO 14229-1:2023 UDS诊断全量测试用例清单系列:第十九节】

ISO 14229-1:2023 UDS诊断服务测试用例全解析&#xff08;ClearDiagnosticInformation_0x84服务&#xff09; 作者&#xff1a;车端域控测试工程师 更新日期&#xff1a;2025年02月14日 关键词&#xff1a;UDS协议、0x84服务、清除诊断信息、ISO 14229-1:2023、ECU测试 一、服…...

自动化测试框架搭建-单次接口执行-三部曲

目的 判断接口返回值和提前设置的预期是否一致&#xff0c;从而判断本次测试是否通过 代码步骤设计 第一步&#xff1a;前端调用后端已经写好的POST接口&#xff0c;并传递参数 第二步&#xff1a;后端接收到参数&#xff0c;组装并请求指定接口&#xff0c;保存返回 第三…...

Spring Bean的生命周期和作用域

一、Bean 生命周期 Bean的定义Bean的实例化属性注入Bean的初始化Bean的使用Bean的销毁 可以增强的位置&#xff1a; PostConstruct&#xff1a;属性注入后&#xff0c;afterPropertiesSet方法 &#xff08;前提实现&#xff1a;InitializingBean接口&#xff09;前增强。 Pr…...

DeepSeek R1生成图片总结2(虽然本身是不能直接生成图片,但是可以想办法利用别的工具一起实现)

DeepSeek官网 目前阶段&#xff0c;DeepSeek R1是不能直接生成图片的&#xff0c;但可以通过优化文本后转换为SVG或HTML代码&#xff0c;再保存为图片。另外&#xff0c;Janus-Pro是DeepSeek的多模态模型&#xff0c;支持文生图&#xff0c;但需要本地部署或者使用第三方工具。…...

ESP32 ESP-IDF TFT-LCD(ST7735 128x160) LVGL基本配置和使用

ESP32 ESP-IDF TFT-LCD(ST7735 128x160) LVGL基本配置和使用 &#x1f4cd;项目地址&#xff1a;https://github.com/lvgl/lv_port_esp32参考文章&#xff1a;https://blog.csdn.net/chentuo2000/article/details/126668088https://blog.csdn.net/p1279030826/article/details/…...

数据库连接池与池化思想

目录 1. 数据库连接池概述 1.1 什么是数据库连接池&#xff1f; 1.2 为什么需要连接池&#xff1f; 2. 池化思想 2.1 池化思想的优点 2.2 池化思想的典型应用 3. 常见的开源数据库连接池 3.1 DBCP 3.2 C3P0 3.3 Druid 4. Druid连接池的使用 4.1 Druid的特点 4.2 D…...