Spring - AOP (面向切面编程)

news/2026/1/21 16:32:12/文章来源:https://www.cnblogs.com/liushoushou/p/19512586

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

1. 核心理论:什么是 AOP?它解决了什么问题?

AOP (Aspect-Oriented Programming),即面向切面编程,是 Spring 框架的另一个核心设计思想,是面向对象编程(OOP)的有力补充。它与 IoC/DI 共同构成了 Spring 的两大基石。

  • 定义: AOP 是一种编程范式,它允许开发者定义横切关注点 (Cross-cutting Concerns),并将其从核心业务逻辑中分离出来,以模块化的方式进行管理。

  • 核心思想: 解耦。它解决了传统 OOP 难以处理的“横切关注点”问题,提高了代码的模块化程度和可维护性。

  • 横切关注点: 指那些遍布于应用程序的多个模块中,但又与核心业务逻辑相对独立的通用功能。例如:

    • 日志记录 (Logging)
    • 事务管理 (Transaction Management)
    • 安全检查 (Security)
    • 性能监控 (Performance Monitoring)
      在传统的 OOP 代码中,这些横切逻辑会散布在各个业务方法中,导致代码冗余,并且难以维护。AOP 则能够将这些通用的、与业务逻辑无关的功能,从核心业务代码中剥离出来,集中管理。
  • 生活比喻:

    • 传统方式 (无 AOP): 你在写一篇小说(核心业务逻辑),但你必须在每个章节的开头和结尾手动添加“版权声明”和“页码”,导致你的小说内容和这些“非核心”内容混杂在一起。
    • AOP 方式 (有 AOP): 你只需要告诉出版社(Spring AOP 框架):“请在我的所有章节的开头加上版权声明,结尾加上页码。”出版社就会自动帮你完成这些工作,你的小说内容依然纯粹,而这些“横切”的功能则由出版社统一处理。

2. 深度剖析:AOP 的核心概念与通知类型

2.1 AOP 核心概念详解

理解 AOP,需要先了解几个核心术语:

  1. 切面 (Aspect): 一个模块化的横切关注点。它通常是一个类,包含了通知 (Advice)切入点 (Pointcut) 的定义。例如,一个负责记录所有方法调用的日志模块就可以是一个切面。
  2. 连接点 (Join Point): 程序执行过程中的一个点,例如方法的执行或异常的处理。在 Spring AOP 中,连接点总是特指方法的执行
  3. 切入点 (Pointcut): 一个表达式,用于定义通知在哪些连接点(哪些方法上)执行。它决定了“在哪做”。
  4. 通知 (Advice): 切面在特定连接点执行的动作。它定义了“在什么时候”和“做什么”,是切面中的具体业务逻辑。
  5. 目标对象 (Target Object): 被一个或多个切面所通知的原始对象。
  6. 织入 (Weaving): 将切面应用到目标对象并创建新的代理对象的过程。Spring AOP 在运行时进行织入。

2.2 常用的通知类型 (Advice Types)

Spring AOP 定义了五种通知类型,它们决定了切面代码在目标方法执行的“何时”运行:

  1. @Before (前置通知)

    • 何时:在目标方法执行之前执行。
    • 作用:常用于权限检查、日志记录、参数校验等。
    • 特点:不能阻止目标方法的执行(除非抛出异常)。
  2. @AfterReturning (后置返回通知)

    • 何时:在目标方法成功执行并返回结果之后执行(即目标方法没有抛出任何异常)。
    • 作用:可以获取到方法的返回值,常用于对返回结果进行处理或记录。
  3. @AfterThrowing (异常通知)

    • 何时:在目标方法抛出异常之后执行。
    • 作用:可以获取到抛出的异常信息,常用于异常处理、错误日志记录、回滚事务等。
  4. @After (后置通知 / 最终通知)

    • 何时:无论目标方法是成功执行、正常返回,还是抛出异常,它总是在目标方法执行之后执行。
    • 作用:类似于 Java 中的 finally 块,常用于资源的释放(如关闭流、释放锁等)。
  5. @Around (环绕通知)

    • 何时:这是功能最强大、最灵活的通知。它“包裹”了整个目标方法的执行。我们可以在方法执行前后自定义逻辑,并且可以控制是否执行目标方法(通过调用 ProceedingJoinPoint.proceed() 方法)、修改目标方法的返回值、或者在调用目标方法前后抛出异常。
    • 作用:常用于复杂的性能监控、事务管理、缓存控制等。
    • 特点:需要接收一个 ProceedingJoinPoint 参数,并必须调用其 proceed() 方法来使目标方法执行,否则目标方法将不会执行。

2.3 AOP 核心概念与执行流程图解

为了更清晰地理解 AOP,我们将结合一个流程图和一个代码执行顺序模拟来看。

场景设定:

  • 目标对象 (Target):一个 UserServiceImpl,它有一个 createUser() 方法。
  • 切面 (Aspect):一个 LoggingAspect,它定义了一个 logBefore() 通知,希望在 createUser() 执行前运行。

流程图

下图展示了一个外部调用,是如何被 Spring AOP 的代理拦截,并一步步执行切面逻辑的。

+--------+   1. 调用 createUser()   +-----------------+ 
| Client | ----------------------> |   Proxy Object  |  (由 Spring AOP 创建)
+--------+                         |  (代理对象)     | +-------+---------+ || 2. 代理拦截调用v
+-------------------------------------------------------------------------+
|                          [ 代理对象内部逻辑 ]                             |
|                                                                         |
|     a) Pointcut 检查: "createUser()方法是否匹配?" -> [是]                 |
|                                                                         |
|     b) 3. 执行 @Before Advice (前置通知)                                 |
|        (调用 LoggingAspect.logBefore())                                 |
|                                                                         |
|           +--------------------------------------------------+          |
|           | 4. 通过反射调用原始对象的方法                      |          |
|           v                                                  |          |
|   +----------------+           +-----------------------------+          |
|   | Target Object  |  <------  |   createUser() 核心业务逻辑   |          |
|   |  (你的原始对象)    |           +-----------------------------+          |
|   +----------------+                  ^                                 |
|           ^                           | 5. 方法返回                     |
|           +---------------------------+                                 |
|                                                                         |
|     c) 6. 执行 @AfterReturning 等后续通知...                             |
|                                                                         |
+-------------------------------------------------------------------------+|| 7. 代理向 Client 返回最终结果v
+--------+
| Client |
+--------+

代理执行流程(文字描述)

  1. 客户端调用代理:客户端代码(如另一个Service或Controller)调用方法,但它实际调用的是Spring生成的代理对象的方法。
  2. 代理逻辑介入:代理对象接收到方法调用后,不会立即执行目标对象的真实方法。相反,它会启动AOP的增强逻辑。
  3. 执行前置/环绕前置通知:代理对象会根据切面配置,首先执行所有适用的前置通知 (@Before)。如果是环绕通知,则执行环绕通知中位于proceed()方法调用之前的部分。
  4. 调用目标方法:在所有前置逻辑执行完毕后,代理对象通过反射(JDK代理)或MethodProxy(CGLIB代理)来调用真实目标对象(Target)的同名方法。
  5. 执行后置/环绕后置通知:在目标方法执行完毕后,代理逻辑继续:
    • 如果目标方法成功执行并返回,代理会执行后置返回通知 (@AfterReturning)
    • 如果目标方法抛出异常,代理会执行异常通知 (@AfterThrowing)
    • 无论目标方法是否成功,代理都会执行最终通知 (@After)
    • 如果是环绕通知,则执行proceed()方法调用之后的部分。
  6. 返回结果:代理对象将目标方法的执行结果(或异常)返回给最初的调用者。

代码执行顺序模拟

上面的流程图在代码层面是如何体现的呢?我们可以把 Spring 创建的那个代理对象想象成下面这个样子:

// 这是 Spring 在运行时为你动态生成的 "UserServiceProxy" 类
// 你看不到这个类的源码,但可以这样理解它的行为public class UserServiceProxy implements UserService {// 1. 代理对象内部,持有你的原始对象 (Target)private UserServiceImpl realUserService;// 2. 代理对象还知道你的切面里有什么逻辑 (Aspect)private LoggingAspect loggingAspect;public UserServiceProxy(UserServiceImpl real, LoggingAspect aspect) {this.realUserService = real;this.loggingAspect = aspect;}// 3. 关键:当你调用 userService.createUser() 时,实际执行的是这个代理方法!@Overridepublic void createUser(String name) {// 这个方法调用本身,就是一个 "Join Point" (连接点)// 4. 在调用真实方法之前,代理会先执行 AOP 逻辑// a. Pointcut (切入点) 检查://    "这个方法 createUser() 是不是我关心的那个?" -> 是的,匹配成功!// b. Advice (通知) 执行://    执行 @Before 通知loggingAspect.logBefore(); // -> 控制台打印 "AOP 日日志:准备执行..."// 5. 调用原始对象的真实方法 (Target)realUserService.createUser(name); // -> 控制台打印 "核心业务:正在创建用户..."// c. 如果有 @After 等通知,会在这里继续执行...}
}

总结:
通过这个代理,Spring AOP 在完全不修改你原始 UserServiceImpl 代码的情况下,成功地在 createUser 方法执行前后插入了额外的日志逻辑,实现了代码的解耦和功能的增强。


2.4 代理的创建时机与执行流程

a) 代理的创建时机

Spring在Bean的生命周期中,通过一个关键的扩展点——BeanPostProcessor来创建代理对象的。

  • 在Bean初始化完成之后,Spring会调用BeanPostProcessorpostProcessAfterInitialization()方法。
  • 其中一个实现AnnotationAwareAspectJAutoProxyCreator会检查当前Bean是否需要被AOP增强。
  • 如果需要,它就会为这个Bean创建一个代理对象,并返回这个代理对象来替换掉容器中原有的Bean实例。

b) 代理的执行流程

当一个被AOP增强的方法被调用时,调用者实际调用的是代理对象的方法。其执行流程如下:

  1. 调用代理对象
  2. 代理逻辑介入,执行前置通知 (@Before)环绕通知的前半部分
  3. 通过反射调用真实目标对象(Target)的同名方法。
  4. 真实方法执行完毕后,代理逻辑继续执行后置通知@AfterReturning, @AfterThrowing, @After)或环绕通知的后半部分
  5. 代理对象将结果返回给调用者。

2.4 多个通知的执行顺序

这是一个非常重要的面试细节题。当多个切面的多个通知作用于同一个方法时,它们的执行顺序遵循以下规则:

a) 不同切面之间的顺序

  • 可以通过在切面类上使用@Order(数字)注解来指定切面的优先级。数字越小,优先级越高
  • 执行顺序(洋葱模型)
    • 进入目标方法时(执行前置通知),优先级越高的切面越先执行
    • 退出目标方法时(执行后置通知),优先级越高的切面越后执行
    • 这形成了一个“洋葱式”的调用结构:高优先级的切面包围着低优先级的切面。

b) 同一个切面内不同通知的顺序

  • 如果一个方法同时被@Around, @Before, @After等多种通知增强,它们的执行顺序是固定的:
    1. @Around环绕通知的前半部分。
    2. @Before前置通知。
    3. 目标方法执行
    4. @Around环绕通知的后半部分。
    5. @After后置通知(最终通知)。
    6. @AfterReturning(如果成功)或@AfterThrowing(如果异常)。

3. 深度剖析:Spring AOP 的实现原理

Spring AOP 的实现原理是基于动态代理模式。它不会直接修改字节码,而是在运行时为目标对象生成一个代理对象,通过代理对象来增强目标对象的功能。

Spring 主要使用以下两种动态代理技术来实现这一过程:

  1. JDK 动态代理

    • 原理:这是 Java 官方提供的代理技术。它通过 Proxy 类和 InvocationHandler 接口,在运行时动态地创建一个实现了目标对象所实现接口的新类(即代理类)。
    • 要求:目标对象必须实现至少一个接口。Spring AOP 会基于这些接口来生成代理对象。
    • 特点:因为代理对象只实现了接口,所以它无法被转型为目标对象的具体类型,只能被转型为接口类型。
    • 如果目标对象实现了接口:Spring默认会使用JDK动态代理。JDK动态代理是基于接口的,它会创建一个实现了与目标对象相同接口的代理类。
  2. CGLIB 动态代理

    • 原理:这是一个第三方的代码生成库。它通过在运行时动态地创建目标对象的一个子类来作为代理对象,并重写父类(即目标对象)的非 final 方法。
    • 要求:目标对象不能是 final,因为 final 类无法被继承。同样,要被代理的方法也不能是 final 的。
    • 特点:因为代理对象是目标对象的子类,所以它可以被转型为目标对象的具体类型。
    • 如果目标对象没有实现任何接口:Spring会使用CGLIB动态代理。CGLIB是基于继承的,它会创建一个目标对象的子类作为代理。

它们之间的主要区别总结如下:

特性 JDK 动态代理 CGLIB 动态代理
实现基础 实现接口 继承父类
依赖 Java 原生支持,无需额外依赖 需要引入 CGLIB 库 (Spring 已内置)
适用对象 必须实现接口的类 普通类 (不能是 final)
性能 在现代 JVM 中,创建和执行性能都非常高 在旧版本中执行效率较高,现在与 JDK 代理性能相当

Spring 的选择策略:

  • 传统的 Spring 框架以及较早的 Spring Boot 版本中,默认策略是:如果一个 Bean 实现了接口,就使用 JDK 动态代理;如果没有,就使用 CGLIB。
  • Spring Boot 2.x 及以后,为了解决 JDK 代理可能带来的类型转换异常(ClassCastException)等问题,默认统一使用 CGLIB,无论目标对象是否实现接口。这个行为可以通过配置文件中的 spring.aop.proxy-target-class 属性来修改。设置为 true (默认) 表示使用 CGLIB,设置为 false 表示如果可能,优先使用 JDK 动态代理。
  • 生活比喻: 想象你有一个私人助理(代理对象)
    • 你(目标对象)只管做自己的事情(核心业务)。
    • 你的助理(代理对象)会帮你处理所有“横切”的事情,比如:在你开会前提醒你带文件(@Before),在你开完会后帮你整理会议室(@After),在你成功完成一个项目后帮你庆祝(@AfterReturning)。
    • 外部的人其实是和你的助理打交道,助理再决定是否把请求转给你。

4. 代码示例:使用 Spring AOP 实现日志记录

我们将通过一个简单的 UserService,使用 Spring AOP 实现方法执行的日志记录。

4.1 接口与实现

// UserService.java (接口)
package com.study.spring.aop;public interface UserService {void addUser(String username);String getUser(String id);
}// UserServiceImpl.java (实现类)
package com.study.spring.aop;import org.springframework.stereotype.Service;@Service
public class UserServiceImpl implements UserService {@Overridepublic void addUser(String username) {System.out.println("UserServiceImpl: Adding user " + username);}@Overridepublic String getUser(String id) {System.out.println("UserServiceImpl: Getting user with ID " + id);return "User-" + id;}
}

4.2 日志切面

// LoggingAspect.java
package com.study.spring.aop;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;@Aspect // 声明这是一个切面
@Component // 声明这是一个 Spring 组件
public class LoggingAspect {// 定义切入点:匹配 com.study.spring.aop 包下所有 UserService 接口的方法@Pointcut("execution(* com.study.spring.aop.UserService.*(..))")public void userServiceMethods() {}// 前置通知:在目标方法执行前执行@Before("userServiceMethods()")public void logBefore(JoinPoint joinPoint) {System.out.println("AOP @Before: " + joinPoint.getSignature().getName() + " 方法开始执行");}// 后置通知:在目标方法执行后(无论成功或异常)执行@After("userServiceMethods()")public void logAfter(JoinPoint joinPoint) {System.out.println("AOP @After: " + joinPoint.getSignature().getName() + " 方法执行结束");}// 返回通知:在目标方法成功返回后执行@AfterReturning(pointcut = "userServiceMethods()", returning = "result")public void logAfterReturning(JoinPoint joinPoint, Object result) {System.out.println("AOP @AfterReturning: " + joinPoint.getSignature().getName() + " 方法成功返回,结果: " + result);}// 异常通知:在目标方法抛出异常后执行@AfterThrowing(pointcut = "userServiceMethods()", throwing = "ex")public void logAfterThrowing(JoinPoint joinPoint, Throwable ex) {System.out.println("AOP @AfterThrowing: " + joinPoint.getSignature().getName() + " 方法抛出异常: " + ex.getMessage());}
}

4.3 Spring 配置与运行

// AppConfig.java (Spring 配置类)
package com.study.spring.aop;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;@Configuration
@ComponentScan("com.study.spring.aop") // 扫描 UserService 和 LoggingAspect
@EnableAspectJAutoProxy // 启用 Spring 对 AspectJ 风格的 AOP 支持
public class AppConfig {
}// MainApp.java
package com.study.spring.aop;import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class MainApp {public static void main(String[] args) {ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);UserService userService = context.getBean(UserService.class);System.out.println("\n--- 调用 addUser ---");userService.addUser("Alice");System.out.println("\n--- 调用 getUser ---");String user = userService.getUser("123");System.out.println("MainApp 收到用户: " + user);}
}

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

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

相关文章

Dify 413 Request Entity Too Large?立即检查这4个核心参数

第一章&#xff1a;Dify 413错误概述与影响分析 在使用 Dify 平台进行应用开发和部署过程中&#xff0c;用户可能会遇到 HTTP 状态码 413 的报错提示。该错误通常表示“Payload Too Large”&#xff0c;即客户端发送的请求数据量超过了服务器所允许的最大限制。这一问题常见于文…

大数据毕设项目推荐-基于大数据的大学生网络行为分析系统基于django的大学生网络行为分析系统【附源码+文档,调试定制服务】

java毕业设计-基于springboot的(源码LW部署文档全bao远程调试代码讲解等) 博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、…

Live Avatar降本方案:单GPU+CPU卸载实现低成本推理案例

Live Avatar降本方案&#xff1a;单GPUCPU卸载实现低成本推理案例 1. 背景与挑战&#xff1a;高显存需求下的推理瓶颈 Live Avatar是由阿里联合高校开源的一款先进的数字人生成模型&#xff0c;能够基于文本、图像和音频输入生成高质量的动态虚拟人物视频。该模型在影视级内容…

Redis:不仅仅是缓存,更是现代系统的数据心脏

前言&#xff1a;为什么Redis被称为“牛逼货”&#xff1f; Redis&#xff08;Remote Dictionary Server&#xff09;自2009年诞生以来&#xff0c;迅速成为全球最受欢迎的开源内存数据库之一。GitHub上超过6.5万星标&#xff0c;Stack Overflow年度调查中连续多年位列“最受欢…

Dify对接飞书审批API全链路详解:从OAuth2鉴权到回调事件处理,98.7%成功率实测验证

第一章&#xff1a;Dify接入飞书审批流自动化流程概述 在企业级应用集成中&#xff0c;将低代码平台与办公协作工具打通是提升运营效率的关键路径。Dify 作为一款支持可视化编排 AI 工作流的开发平台&#xff0c;具备强大的外部系统集成能力。通过接入飞书开放平台的审批 API&a…

语音大数据处理新思路:FSMN-VAD批量检测自动化实践

语音大数据处理新思路&#xff1a;FSMN-VAD批量检测自动化实践 1. FSMN-VAD 离线语音端点检测控制台 在语音数据预处理的工程实践中&#xff0c;如何高效、准确地从长音频中提取有效语音片段&#xff0c;一直是提升后续识别与分析效率的关键环节。传统的手动切分方式耗时耗力…

性价比之王!加压流体萃取仪价格便宜、质量靠谱厂家推荐

在分析实验室的日常运作中,加压流体萃取仪(PFE)已成为环境监测、食品安全、药物分析等领域不可或缺的样品前处理利器。然而,面对市场上众多国内外品牌,实验室管理者们往往陷入选择困境:究竟哪家仪器更经久耐用?…

CAM++ WebUI使用手册:科哥开发的界面功能全解析

CAM WebUI使用手册&#xff1a;科哥开发的界面功能全解析 1. 系统简介与核心能力 CAM 是一个基于深度学习的说话人识别系统&#xff0c;由开发者“科哥”进行WebUI二次开发后&#xff0c;实现了直观、易用的操作界面。该系统能够精准判断两段语音是否来自同一说话人&#xff…

Z-Image-Turbo适合内容创作者?图文搭配生成实战教程

Z-Image-Turbo适合内容创作者&#xff1f;图文搭配生成实战教程 1. 内容创作新利器&#xff1a;Z-Image-Turbo到底有多强&#xff1f; 你有没有遇到过这种情况&#xff1a;脑子里有个很棒的画面&#xff0c;想做封面、配图或者社交媒体素材&#xff0c;但找图找不到合适的&am…

北京上门回收紫檀红木家具 丰宝斋旧件修复评估更公道

不少老旧紫檀、红木家具因年代久远,存在部件缺失、榫卯松动、表面磨损等问题,藏家想变现却怕被回收商以“破损严重”为由大幅压价,甚至直接拒收。普通回收商只看重完好家具的价值,缺乏旧件修复评估能力,无法客观核…

输入方言词汇,自动转为普通话释义和发音,同时匹配方言例句,适配不同地域人群的语言沟通需求。

设计一个 基于 Python 的方言-普通话互译与学习工具&#xff0c;满足你的要求&#xff0c;并特别考虑不同地域人群的语言沟通需求。1. 实际应用场景描述场景&#xff1a;在跨地域交流、旅游、商务合作或文化研究中&#xff0c;常遇到方言词汇听不懂、说不准的问题。例如&#x…

新手前端别慌:CSS3字体样式一文搞定(附避坑指南)

新手前端别慌&#xff1a;CSS3字体样式一文搞定&#xff08;附避坑指南&#xff09;新手前端别慌&#xff1a;CSS3字体样式一文搞定&#xff08;附避坑指南&#xff09;字体的“户口本”&#xff1a;font-family 到底该怎么写才不死机字号单位大乱斗&#xff1a;px、em、rem、%…

dify高可用架构设计全解析(企业级部署方案揭秘)

第一章&#xff1a;dify高可用架构设计全解析&#xff08;企业级部署方案揭秘&#xff09; 在构建面向生产环境的企业级AI应用平台时&#xff0c;dify的高可用架构设计成为保障系统稳定与服务连续性的核心。通过分布式部署、服务解耦与自动化运维机制&#xff0c;dify能够实现跨…

FSMN-VAD适合嵌入式吗?轻量级部署可行性分析

FSMN-VAD适合嵌入式吗&#xff1f;轻量级部署可行性分析 1. 引言&#xff1a;为什么关注FSMN-VAD的嵌入式适用性&#xff1f; 语音端点检测&#xff08;Voice Activity Detection, VAD&#xff09;是语音处理流水线中的关键第一步。它负责从连续音频中准确识别出“什么时候有…

别再用闭源向量库了!Dify接入Milvus的3大优势与避坑指南

第一章&#xff1a;别再用闭源向量库了&#xff01;Dify接入Milvus的3大优势与避坑指南 在构建AI应用时&#xff0c;向量数据库的选择直接影响系统的性能、成本和可扩展性。Dify作为主流的低代码AI应用开发平台&#xff0c;支持灵活集成外部向量库。相比闭源方案&#xff0c;开…

【大数据毕设全套源码+文档】基于springboot的大型超市数据处理系统设计与实现(丰富项目+远程调试+讲解+定制)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

Z-Image-Turbo提示词工程怎么做?结构化输入优化教程

Z-Image-Turbo提示词工程怎么做&#xff1f;结构化输入优化教程 Z-Image-Turbo是阿里巴巴通义实验室开源的高效AI图像生成模型&#xff0c;作为Z-Image的蒸馏版本&#xff0c;它在保持高质量输出的同时大幅提升了推理速度。仅需8步即可生成一张细节丰富、风格多样的图像&#…

kylin-安装vscode过程与方法

kylin-安装vscode过程与方法进行“sftp://172.11.204.26/root/zhujq/tools/vscode” 打开“在终端中打开” 输入“dpkg -i code_1.75.1-1675893397_amd64.deb” 回车 vscode安装结束 但是这时点击vscode,你会发现打不…

【MCP Server部署终极指南】:手把手教你3步发布到GitHub供团队使用

第一章&#xff1a;MCP Server与GitHub集成概述 在现代软件开发实践中&#xff0c;持续集成与持续部署&#xff08;CI/CD&#xff09;已成为提升代码质量与交付效率的核心机制。MCP Server&#xff08;Microservice Control Platform Server&#xff09;作为微服务架构下的控制…

蚂蚁集团革命性突破:如何让AI更智能地筛选信息

在信息爆炸的时代&#xff0c;当我们向搜索引擎询问一个复杂问题时&#xff0c;系统需要从数百万个网页中找出最有用的那几个。这个看似简单的任务&#xff0c;实际上是一个极其复杂的技术难题。蚂蚁集团的研究团队最近在这个领域取得了重大突破&#xff0c;他们开发出一种名为…