深入解析代理模式:静态代理、JDK 动态代理和 CGLIB 的全方位对比!
代理模式(Proxy Pattern)是一种结构型设计模式,它提供了对象的替身,即代理对象来控制对实际对象的访问。通过代理对象,可以在不修改目标对象的情况下,扩展或控制其功能。例如,代理模式可以用于延迟加载、权限控制、日志记录等场景。
🎯 核心要点:
- 代理对象:代理模式通过代理对象替代实际对象进行控制,代理对象和实际对象实现相同的接口。
- 控制访问:代理对象可以控制客户端与实际对象的交互,甚至对客户端的请求进行预处理或后处理。
- 延迟初始化:代理对象可以在需要的时候才创建实际对象,节省资源。
UML类图

Subject:这是接口,定义了代理对象和实际对象都要实现的公共接口,包含方法 request()。
RealSubject:实现 Subject 接口的类,表示真正执行操作的对象。
Proxy:同样实现了 Subject 接口,代理 RealSubject 对象,控制对 RealSubject 的访问
静态代理
静态代理是指在编译期就已经确定了代理类。我们必须手动创建代理类,并明确代理哪个对象。代理类与被代理类实现相同的接口,通过代理类来控制对实际对象的访问。
静态代理案例:银行账户管理
假设我们有一个银行账户管理系统,用户通过 BankAccount 类管理账户余额,BankAccountProxy 作为代理类,添加了权限控制功能,只有拥有特定权限的用户才能执行账户操作
。
案例场景:
- 实际对象:
BankAccount负责执行账户的具体操作(如查询余额)。 - 代理对象:
BankAccountProxy负责控制对BankAccount的访问,确保只有权限用户可以操作账户。
静态代理代码实现
Step 1: 定义接口
// Subject 接口
public interface BankAccount {void deposit(double amount);void withdraw(double amount);double getBalance();
}
Step 2: 实现具体的银行账户类
// RealSubject 实现类
public class RealBankAccount implements BankAccount {private double balance;public RealBankAccount(double initialBalance) {this.balance = initialBalance;}@Overridepublic void deposit(double amount) {balance += amount;System.out.println("Deposited " + amount + ", new balance is " + balance);}@Overridepublic void withdraw(double amount) {if (amount <= balance) {balance -= amount;System.out.println("Withdrew " + amount + ", new balance is " + balance);} else {System.out.println("Insufficient funds.");}}@Overridepublic double getBalance() {return balance;}
}
Step 3: 实现代理类
// Proxy 类
public class BankAccountProxy implements BankAccount {private RealBankAccount realBankAccount;private String userRole;public BankAccountProxy(RealBankAccount realBankAccount, String userRole) {this.realBankAccount = realBankAccount;this.userRole = userRole;}@Overridepublic void deposit(double amount) {if (userRole.equals("Admin")) {realBankAccount.deposit(amount);} else {System.out.println("Access denied: You don't have permission to deposit.");}}@Overridepublic void withdraw(double amount) {if (userRole.equals("Admin")) {realBankAccount.withdraw(amount);} else {System.out.println("Access denied: You don't have permission to withdraw.");}}@Overridepublic double getBalance() {return realBankAccount.getBalance();}
}
Step 4: 测试代理类
public class Client {public static void main(String[] args) {// 创建真实对象和代理对象RealBankAccount realAccount = new RealBankAccount(1000);BankAccount proxyAccount = new BankAccountProxy(realAccount, "User");// 测试代理访问proxyAccount.deposit(500); // 访问受限proxyAccount.withdraw(300); // 访问受限// 以 Admin 身份访问BankAccount adminAccount = new BankAccountProxy(realAccount, "Admin");adminAccount.deposit(500); // 成功存款adminAccount.withdraw(300); // 成功取款}
}
输出结果:
Access denied: You don't have permission to deposit.
Access denied: You don't have permission to withdraw.
Deposited 500.0, new balance is 1500.0
Withdrew 300.0, new balance is 1200.0
解释:
- 权限控制:
BankAccountProxy控制了对RealBankAccount的访问,只有拥有 Admin 权限的用户才能操作账户。 - 灵活扩展:通过代理类,我们可以在不修改
RealBankAccount的前提下,灵活地添加权限控制功能。
动态代理(JDK 动态代理)
动态代理是在运行时动态生成代理类,而不是在编译时确定。动态代理可以通过反射机制自动生成代理对象,而无需手动编写代理类。
动态代理案例:银行账户管理(JDK 动态代理)
在 动态代理 中,代理类是在运行时动态生成的。Java 提供了 java.lang.reflect.Proxy 类和 InvocationHandler 接口来实现动态代理。
案例场景:
和静态代理案例类似,我们还是使用 BankAccount 管理账户,但是通过 JDK 动态代理 来动态生成代理类,代理类控制用户的操作权限,并记录日志
。
动态代理代码实现
Step 1: 定义接口(与静态代理相同)
// Subject 接口
public interface BankAccount {void deposit(double amount);void withdraw(double amount);double getBalance();
}
Step 2: 实现具体的银行账户类(与静态代理相同)
// RealSubject 实现类
public class RealBankAccount implements BankAccount {private double balance;public RealBankAccount(double initialBalance) {this.balance = initialBalance;}@Overridepublic void deposit(double amount) {balance += amount;System.out.println("Deposited " + amount + ", new balance is " + balance);}@Overridepublic void withdraw(double amount) {if (amount <= balance) {balance -= amount;System.out.println("Withdrew " + amount + ", new balance is " + balance);} else {System.out.println("Insufficient funds.");}}@Overridepublic double getBalance() {return balance;}
}
Step 3: 实现 InvocationHandler 接口
InvocationHandler 是动态代理的核心,通过 invoke() 方法拦截对目标对象的方法调用。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;public class BankAccountInvocationHandler implements InvocationHandler {private Object target;private String userRole;public BankAccountInvocationHandler(Object target, String userRole) {this.target = target;this.userRole = userRole;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if (userRole.equals("Admin")) {System.out.println("Admin access granted.");return method.invoke(target, args); // 调用目标对象的方法} else {System.out.println("Access denied: You don't have permission to " + method.getName());return null;}}
}
Step 4: 动态代理测试
import java.lang.reflect.Proxy;public class Client {public static void main(String[] args) {// 创建真实对象RealBankAccount realAccount = new RealBankAccount(1000);// 创建动态代理对象BankAccount proxyAccount = (BankAccount) Proxy.newProxyInstance(realAccount.getClass().getClassLoader(),new Class[]{BankAccount.class},new BankAccountInvocationHandler(realAccount, "User"));// 测试代理访问proxyAccount.deposit(500); // 访问受限proxyAccount.withdraw(300); // 访问受限// 以 Admin 身份访问BankAccount adminAccount = (BankAccount) Proxy.newProxyInstance(realAccount.getClass().getClassLoader(),new Class[]{BankAccount.class},new BankAccountInvocationHandler(realAccount, "Admin"));adminAccount.deposit(500); // 成功存款adminAccount.withdraw(300); // 成功取款}
}
输出结果:
Access denied: You don't have permission to deposit
Access denied: You don't have permission to withdraw
Admin access granted.
Deposited 500.0, new balance is 1500.0
Admin access granted.
Withdrew 300.0, new balance is 1200.0
解释:
- 运行时生成代理类:通过
Proxy.newProxyInstance()方法,动态生成代理类。 - 权限控制:动态代理可以在运行时灵活地进行权限控制,且不需要手动创建代理类。
CGLIB 动态代理
通过生成目标类的子类,并重写其中的方法来实现代理。它是在运行时生成的字节码,所以可以代理普通类和接口。代理类实际上是目标类的子类,并且会调用父类的方法。
- 依赖:需要导入
cglib相关的库。 - 限制:由于 CGLIB 是通过继承实现的,所以不能代理
final类或**final方法**,因为这些无法被继承和重写。
CGLIB 依赖导入
在项目中,你需要下载CGLIB相关的所有JAR包,或者使用 Maven 或 Gradle 导入 cglib 依赖
Jar包下载地址:相关JAR点击下载
Maven 依赖:
<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.3.0</version>
</dependency>
Gradle 依赖:
implementation 'cglib:cglib:3.3.0'
案例场景:银行账户管理(CGLIB 动态代理)
我们将基于前面的银行账户管理系统,使用 CGLIB 实现动态代理,控制用户操作权限并记录日志
。
场景:
- 实际对象:
BankAccount是一个普通类,没有实现任何接口。 - 代理对象:使用 CGLIB 动态生成代理类,实现权限控制和日志功能
CGLIB 动态代理代码实现
Step 1: 创建 BankAccount 类
不再实现接口,这是一个普通类,CGLIB 可以代理这个类。
// RealSubject 实现类,普通类,没有实现接口
public class BankAccount {private double balance;public BankAccount(double initialBalance) {this.balance = initialBalance;}public void deposit(double amount) {balance += amount;System.out.println("Deposited " + amount + ", new balance is " + balance);}public void withdraw(double amount) {if (amount <= balance) {balance -= amount;System.out.println("Withdrew " + amount + ", new balance is " + balance);} else {System.out.println("Insufficient funds.");}}public double getBalance() {return balance;}
}
Step 2: 创建 MethodInterceptor 实现类
MethodInterceptor 是 CGLIB 代理的核心,通过重写 intercept() 方法来拦截目标类的方法调用
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;public class BankAccountMethodInterceptor implements MethodInterceptor {private String userRole;public BankAccountMethodInterceptor(String userRole) {this.userRole = userRole;}@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {if (userRole.equals("Admin")) {System.out.println("Admin access granted.");return proxy.invokeSuper(obj, args); // 调用父类的原方法} else {System.out.println("Access denied: You don't have permission to " + method.getName());return null;}}
}
Step 3: 使用 Enhancer 动态生成代理类
CGLIB 使用 Enhancer 类来生成代理对象,Enhancer 会生成一个目标类的子类,并将方法调用委托给 MethodInterceptor。
import net.sf.cglib.proxy.Enhancer;public class Client {public static void main(String[] args) {// 创建 Enhancer 对象Enhancer enhancer = new Enhancer();enhancer.setSuperclass(BankAccount.class); // 设置代理目标类enhancer.setCallback(new BankAccountMethodInterceptor("User")); // 设置拦截器// 创建代理对象BankAccount proxyAccount = (BankAccount) enhancer.create(new Class[]{double.class}, new Object[]{1000.0});// 测试代理访问proxyAccount.deposit(500); // 访问受限proxyAccount.withdraw(300); // 访问受限// 以 Admin 身份访问enhancer.setCallback(new BankAccountMethodInterceptor("Admin"));BankAccount adminAccount = (BankAccount) enhancer.create(new Class[]{double.class}, new Object[]{1000.0});adminAccount.deposit(500); // 成功存款adminAccount.withdraw(300); // 成功取款}
}
输出结果:
Access denied: You don't have permission to deposit
Access denied: You don't have permission to withdraw
Admin access granted.
Deposited 500.0, new balance is 1500.0
Admin access granted.
Withdrew 300.0, new balance is 1200.0
解释:
- 动态生成代理类:通过
Enhancer类,动态生成了BankAccount类的代理对象。 - 权限控制:
MethodInterceptor控制了对目标方法的调用,只有具有 Admin 权限的用户才能执行操作。 - 日志功能:代理类在执行目标方法前,打印日志信息。
CGLIB 动态代理的优缺点
优点:
- 支持无接口类的代理:CGLIB 能够代理普通类,不要求目标类必须实现接口,这比 JDK 动态代理更灵活。
- 性能高:相比 JDK 动态代理,CGLIB 生成的代理类性能更高,尤其是在大量调用代理方法的场景下。
- 透明性:客户端无需修改,代理类的生成是透明的。
缺点:
- 不能代理
final类和方法:由于 CGLIB 代理是通过生成子类实现的,因此无法代理final类和final方法。 - 依赖第三方库:CGLIB 是一个外部库,增加了项目的依赖复杂度。
总结:CGLIB 动态代理的特点
- 代理普通类:CGLIB 允许代理没有实现接口的类,这比 JDK 动态代理更加灵活。
- 通过继承实现代理:CGLIB 生成目标类的子类,并重写目标方法来实现代理。
- 应用场景广泛:CGLIB 动态代理适用于需要代理普通类、且调用频繁的场景。
🎯 Spring AOP 代理机制
Spring AOP(Aspect-Oriented Programming,面向切面编程)是 Spring 框架中的核心特性之一,它通过代理对象来对目标对象的方法进行拦截,在方法执行前后加入额外的逻辑,如日志记录、权限验证、事务管理等。
Spring AOP 中使用了两种代理机制:
- JDK 动态代理(基于接口的代理)
- CGLIB 动态代理(基于子类的代理)
使用的代理类型
- JDK 动态代理:当目标类实现了接口时,Spring AOP 默认使用 JDK 动态代理来生成代理对象。
- CGLIB 动态代理:当目标类没有实现接口时,Spring AOP 会使用 CGLIB 来生成代理对象。
Spring AOP 如何选择代理机制
Spring 选择代理的规则:
- 如果目标对象实现了接口,Spring AOP 默认使用 JDK 动态代理。
- 如果目标对象没有实现接口,Spring AOP 使用 CGLIB 动态代理。
- 可以强制使用 CGLIB:即使目标对象实现了接口,也可以通过配置来强制使用 CGLIB 代理。
Spring AOP 动态代理应用场景
Spring AOP 的代理机制广泛应用于以下场景:
- 事务管理:通过代理对象,在方法执行时自动管理事务的开启和提交。
- 日志记录:在方法执行前后自动添加日志记录。
- 权限控制:通过代理对象,控制用户是否有权限调用某些方法。
- 缓存机制:在方法执行前,先检查缓存,如果缓存中存在结果则直接返回,否则执行目标方法并将结果存入缓存
三种代理类型的对比
下表详细对比了 静态代理、JDK 动态代理 和 CGLIB 动态代理 的不同点。
| 对比维度 | 静态代理 | JDK 动态代理 | CGLIB 动态代理 |
|---|---|---|---|
| 实现方式 | 手动创建代理类 | 通过 Proxy 类和 InvocationHandler 动态生成 | 通过继承目标类,使用字节码生成子类 |
| 是否需要接口 | 是,需要代理类和目标类实现相同接口 | 是,必须代理实现了接口的类 | 否,不需要接口,直接代理类本身 |
| 代理类生成时间 | 编译时生成,代码已确定 | 运行时动态生成 | 运行时动态生成 |
| 实现复杂度 | 需要手动编写代理类,代码重复 | 较简单,自动生成代理类 | 复杂度较高,需要字节码生成库 |
| 方法调用方式 | 代理类直接调用目标类方法 | 代理对象通过 InvocationHandler 反射调用目标方法 | 通过字节码技术生成子类,直接调用父类方法 |
| 代理性能 | 性能较好,方法直接调用 | 性能较差,基于反射调用,反射开销大 | 性能较高,生成的子类直接调用父类方法 |
| 代理对象结构 | 代理对象和目标对象有相同的接口 | 代理对象和目标对象实现相同接口 | 代理对象是目标类的子类 |
| 应用场景 | 适用于代理数量少、简单的场景 | 适用于需要代理实现接口的场景 | 适用于没有实现接口的类,或者需要大量代理的场景 |
是否可代理 final 类 | 是 | 否,无法代理 final 类 | 否,无法代理 final 类 |
| 优点 | 实现简单,直观 | 灵活,可以代理接口,易于扩展 | 可代理普通类,性能较高,适用于没有接口的类 |
| 缺点 | 需要为每个目标类手动编写代理类,代码冗余 | 只能代理接口,基于反射调用性能较低 | 无法代理 final 类,依赖外部库,配置较复杂 |
总结:三种代理的特点和适用场景
- 静态代理:
- 特点:代理类由开发者手动编写,固定且已确定,代码较多、可维护性较低。
- 适用场景:代理类少、功能固定的场景,简单、容易实现。
- JDK 动态代理:
- 特点:只能代理实现了接口的类,通过反射调用目标方法,代理类在运行时生成,性能相对较低。
- 适用场景:目标对象实现了接口,尤其是需要动态代理多个接口的场景,如日志记录、权限控制等。
- CGLIB 动态代理:
- 特点:不要求目标类必须实现接口,使用字节码生成技术生成目标类的子类,性能高于 JDK 动态代理,但无法代理
final类和final方法。 - 适用场景:目标类没有实现接口,且代理调用频繁时使用,尤其适合对普通类的代理
- 特点:不要求目标类必须实现接口,使用字节码生成技术生成目标类的子类,性能高于 JDK 动态代理,但无法代理
相关文章:
深入解析代理模式:静态代理、JDK 动态代理和 CGLIB 的全方位对比!
代理模式(Proxy Pattern)是一种结构型设计模式,它提供了对象的替身,即代理对象来控制对实际对象的访问。通过代理对象,可以在不修改目标对象的情况下,扩展或控制其功能。例如,代理模式可以用于延…...
51单片机快速入门之独立按键
51单片机快速入门之独立按键 这里我们需要用上一个仿真软件,只因不想硬件焊接:PROTEUS DESIGN SUITE PROTEUS DESIGN SUITE: PROTEUS DESIGN SUITE是一款由LabCenter Electronics开发的电子设计自动化(EDA)软件,广泛应用于电气工程和电子工…...
设计模式之工厂模式(通俗易懂--代码辅助理解【Java版】)
文章目录 设计模式概述1、工厂模式概述1)特点:2)主要角色:3)工作流程:4)优点5)缺点6)适用场景 2、简单工厂模式(静态工厂模式)1) 在简单工厂模式中,有三个主要…...
速盾:高防 cdn 分布式防御攻击?
在当今数字化时代,网络安全问题日益凸显,各种网络攻击手段层出不穷。为了保护企业和个人的网络资产安全,高防 CDN(Content Delivery Network,内容分发网络)成为了一种重要的防御手段。其中,分布…...
Unity3D类似于桌面精灵的功能实现
前言: 由于最近在做游戏魔改,很多功能在游戏里面没法实现(没错,说的就是排行榜),所以准备用Unity3D开发一个类似于桌面精灵的功能部件,实现效果如下: PS:有需要定制的老…...
Audio Over IP的PTP时钟初探
Audio Over IP的PTP时钟初探 这几天参加省局举办的技术能手比赛,第一次接触并了解AOIP(Audio Over IP)相关的理论和实践相关的知识。其中AoIP的时钟同步采用的是IEEE 1588 标准的PTP(Precision Time Protocol)基于网络…...
【加密社】深入理解TON智能合约 (FunC语法)
king: 摘要:在TON(TheOpenNetwork)区块链平台中,智能合约扮演着举足轻重的角色。本文将通过分析一段TON智能合约代码 带领读者学习dict(字典)和list(列表)在FunC语言中的用法&#x…...
笔试强训day11
游游的水果大礼包 #include <iostream> #define int long longusing namespace std; int n, m, a, b;signed main() {cin>>n>>m>>a>>b;int ret 0;for(int x 0; x < min(n / 2, m); x) // 枚举 1 号礼包的个数{int y min(n - x * 2, (m - …...
移动应用开发与测试赛题
引言 在现代车载系统开发中,UI设计和编程实现同样重要。本文将分别探讨车载系统的UI设计任务和相关的编程任务,帮助开发者全面了解车载系统开发的各个方面。 第一部分:UI设计任务 任务1:绘制"左转向视频显示"模块界面…...
Qt常用控件——QLineEdit
文章目录 QLineEdit核心属性和信号基本示例正则表达式约束验证输入密码是否一致密码显示状态切换 QLineEdit核心属性和信号 QLineEdit用来表示单行输入,可以输入一段文本,但是不能替换 核心属性: 属性说明text输入框中的文本inputMask输入…...
(postman)接口测试进阶实战
1.内置和自定义的动态参数 内置的动态参数有哪些? ---{{$}}--是内置动态参数的标志 //自定义的动态参数 此处date.now()的作用就相当于上面的timestamp 2.业务闭环及文件接口测试 返回的url地址可以在网页中查询得到。 3. 常规断言,动态参数断言…...
R语言统计分析——功效分析(比例、卡方检验)
参考资料:R语言实战【第2版】 1、比例检验 当比较两个比例时,可使用pwr.2p.test()函数进行功效分析。格式为: pwr.2p.test(h, n, sig.level, power, alternative) 其中,h是效应值,n是各相同的样本量。效应值h的定义如…...
Leetcode 每日一题:Longest Increasing Path in a Matrix
写在前面: 今天我们继续看一道 图论和遍历 相关的题目。这道题目的背景是在一个矩阵当中找寻最长的递增数列长度。思路上非常好想,绝对和 DFS 相关,但是题目的优化要求非常高,对于语言和内存特性的考察特别丰富,如果是…...
ARCGIS PRO DSK MapTool
MapTool用于自定义地图操作工具,使用户能够在ArcGIS Pro中执行特定的地图交互操作。添加 打开MapTool1.vb文件,可以看到系统已经放出MapTool1类: Public Sub New()将 IsSketchTool 设置为 true 以使此属性生效IsSketchTool TrueSketchTyp…...
国网B接口 USC安防平台 海康摄像机配置
国网B接口海康摄像机配置介绍 如下以海康DS-NACN6432I-GLN摄像机为例,配置国网B接口设备接入流程,海康摄像机的固件版本为 V5.6.11 build 210109 210107。该设备为球机,支持国网B接口云台控制功能。图标编号可以对应二者的配置。 注意 同一…...
Win10安装.net FrameWork3.5失败解决方法
win10安装.net FrameWork3.5失败解决方法 已经好久没有来投稿了,实在最近业务缠身,忙的焦头烂额(呵~多么伟大的牛马) 但最近开发使用windows11实在是拉胯的不行,升级完就后悔,所以就一怒之下,重装了win10 可是,好家伙,我重装完遇到一个问题,就是在使用.Net Framework3.5,按照Mi…...
【pipenv】—— 虚拟环境管理工具近乎全面的总结
安装 pip install pipenv 使用和配置 设置虚拟环境文件创建在项目根目录 添加环境变量:WORKON_HOMEPIPENV_VENV_IN_PROJECT 创建虚拟环境时,自动换用指定的pip源 添加环境变量:PIPENV_TEST_INDEXhttps://pypi.tuna.tsinghua.edu…...
windows C++-并行编程-并行算法(五) -选择排序算法
并行模式库 (PPL) 提供了对数据集合并行地执行工作的算法。这些算法类似于 C 标准库提供的算法。并行算法由并发运行时中的现有功能组成。 在许多情况下,parallel_sort 会提供速度和内存性能的最佳平衡。 但是,当您增加数据集的大小、可用处理器的数量或…...
【系统架构设计师-2014年真题】案例分析-答案及详解
更多内容请见: 备考系统架构设计师-核心总结索引 文章目录 【材料1】问题1问题2【材料2】问题1问题2问题3【材料3】问题1问题2问题3【材料4】问题1问题2【材料5】问题1问题2问题3【材料1】 请详细阅读以下关于网络设备管理系统架构设计的说明,在答题纸上回答问题1和问题2。 …...
windows C++-并行编程-并行算法(三)-分区工作
并行模式库 (PPL) 提供了对数据集合并行地执行工作的算法。这些算法类似于 C 标准库提供的算法。并行算法由并发运行时中的现有功能组成。 若要对数据源操作进行并行化,一个必要步骤是将源分区为可由多个线程同时访问的多个部分。 分区程序将指定并行算法应如何在线…...
铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...
为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...
MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
动态 Web 开发技术入门篇
一、HTTP 协议核心 1.1 HTTP 基础 协议全称 :HyperText Transfer Protocol(超文本传输协议) 默认端口 :HTTP 使用 80 端口,HTTPS 使用 443 端口。 请求方法 : GET :用于获取资源,…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...
[ACTF2020 新生赛]Include 1(php://filter伪协议)
题目 做法 启动靶机,点进去 点进去 查看URL,有 ?fileflag.php说明存在文件包含,原理是php://filter 协议 当它与包含函数结合时,php://filter流会被当作php文件执行。 用php://filter加编码,能让PHP把文件内容…...
手机平板能效生态设计指令EU 2023/1670标准解读
手机平板能效生态设计指令EU 2023/1670标准解读 以下是针对欧盟《手机和平板电脑生态设计法规》(EU) 2023/1670 的核心解读,综合法规核心要求、最新修正及企业合规要点: 一、法规背景与目标 生效与强制时间 发布于2023年8月31日(OJ公报&…...
go 里面的指针
指针 在 Go 中,指针(pointer)是一个变量的内存地址,就像 C 语言那样: a : 10 p : &a // p 是一个指向 a 的指针 fmt.Println(*p) // 输出 10,通过指针解引用• &a 表示获取变量 a 的地址 p 表示…...
