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

深入解析 Java 代理:从静态代理到 CGLIB,掌握 AOP 底层核心

代理模式是 Java 设计模式中结构型模式的核心代表,更是 Spring AOP、事务管理、RPC 框架、日志拦截等核心技术的底层实现基石。理解 Java 代理的实现原理,不仅能掌握设计模式的实战应用,更能打通 Spring 等主流框架的底层逻辑。本文将从代理模式的核心思想出发,逐层拆解静态代理、JDK 动态代理、CGLIB 代理的实现细节、底层原理、优缺点及实战场景,最终带你掌握 AOP 技术的核心本质。

一、代理模式的核心本质

1.1 代理模式的定义

代理模式(Proxy Pattern):为目标对象提供一个代理对象,由代理对象控制对目标对象的访问。代理对象作为 “中间层”,既可以保护目标对象,也可以在不修改目标对象源码的前提下,对目标对象的功能进行扩展(如添加日志、权限校验、性能监控等)。

1.2 生活中的代理类比

  • 租房中介:你(客户端)不直接对接房东(目标对象),而是通过中介(代理对象)完成租房流程,中介会帮你筛选房源、审核资质(附加功能),最终完成租房(核心功能);
  • 明星经纪人:经纪人(代理)负责对接演出、洽谈费用(附加功能),明星(目标)只需要专注表演(核心功能);
  • 律师代理:律师(代理)处理法律流程(附加功能),当事人(目标)只需陈述事实(核心功能)。

1.3 代理模式的核心角色

代理模式的核心包含 4 个角色,所有代理实现都围绕这 4 个角色展开:

角色名称核心职责
抽象主题(Subject)定义目标对象和代理对象的共同接口 / 抽象类,确保代理对象可替代目标对象(里氏替换原则);
真实主题(RealSubject)真正执行业务逻辑的目标对象,是代理的最终调用目标;
代理对象(Proxy)实现 / 继承抽象主题,持有真实主题的引用,在调用目标方法前后添加附加逻辑;
客户端(Client)仅与代理对象交互,不直接操作真实主题;

1.4 代理模式的核心价值

  • 解耦:将核心业务逻辑(如用户新增)与非核心逻辑(如日志、事务)分离,符合 “单一职责原则”;
  • 扩展:无需修改目标对象源码,通过代理即可新增功能(开放封闭原则);
  • 控制:可控制对目标对象的访问(如权限校验、限流、熔断);
  • 隐藏:可隐藏目标对象的实现细节(如 RPC 代理隐藏远程调用细节)。

二、静态代理:手动编写的 “专属代理”

静态代理是最基础的代理实现方式,代理类由开发者手动编写,在编译期就确定了代理类与目标类的绑定关系,属于 “一对一” 的专属代理。

2.1 实现步骤

  1. 定义抽象主题接口,声明核心业务方法;
  2. 实现真实主题类,完成核心业务逻辑;
  3. 编写代理类,实现抽象主题接口,持有真实主题引用;
  4. 在代理类的方法中,调用目标方法并添加附加逻辑;
  5. 客户端通过代理类调用业务方法。

2.2 实战案例:用户服务日志代理

以 “用户新增功能” 为例,通过静态代理添加日志记录功能。

步骤 1:定义抽象主题接口
/** * 抽象主题:用户服务接口(定义核心业务方法) */ public interface UserService { /** * 新增用户 * @param username 用户名 * @param age 年龄 * @return 是否新增成功 */ boolean addUser(String username, int age); }
步骤 2:实现真实主题类
/** * 真实主题:用户服务实现类(核心业务逻辑) */ public class UserServiceImpl implements UserService { @Override public boolean addUser(String username, int age) { // 核心业务逻辑:模拟数据库新增用户 if (username == null || username.isEmpty()) { throw new IllegalArgumentException("用户名不能为空"); } System.out.println("【核心逻辑】新增用户:" + username + ",年龄:" + age); return true; } }
步骤 3:编写静态代理类
/** * 静态代理类:为UserService添加日志功能 */ public class UserServiceStaticProxy implements UserService { // 持有真实主题引用 private final UserService target; // 通过构造器注入目标对象 public UserServiceStaticProxy(UserService target) { this.target = target; } @Override public boolean addUser(String username, int age) { // 1. 前置附加逻辑:日志记录(方法调用前) System.out.println("【静态代理-前置】开始调用addUser方法,参数:username=" + username + ", age=" + age); long startTime = System.currentTimeMillis(); boolean result = false; try { // 2. 调用目标对象的核心方法 result = target.addUser(username, age); // 3. 后置附加逻辑:日志记录(方法调用成功) System.out.println("【静态代理-后置】addUser方法调用成功,返回结果:" + result); return result; } catch (Exception e) { // 4. 异常附加逻辑:日志记录(方法调用异常) System.out.println("【静态代理-异常】addUser方法调用失败,异常信息:" + e.getMessage()); throw e; // 抛出异常,不影响上层处理 } finally { // 5. 收尾逻辑:性能监控 long endTime = System.currentTimeMillis(); System.out.println("【静态代理-耗时】addUser方法执行耗时:" + (endTime - startTime) + "ms"); } } }
步骤 4:客户端测试
/** * 客户端:通过静态代理调用目标方法 */ public class StaticProxyClient { public static void main(String[] args) { // 1. 创建真实目标对象 UserService target = new UserServiceImpl(); // 2. 创建代理对象,注入目标对象 UserService proxy = new UserServiceStaticProxy(target); // 3. 调用代理方法(正常场景) System.out.println("===== 正常场景 ====="); proxy.addUser("张三", 25); // 4. 调用代理方法(异常场景) System.out.println("\n===== 异常场景 ====="); try { proxy.addUser("", 20); } catch (IllegalArgumentException e) { System.out.println("客户端捕获异常:" + e.getMessage()); } } }
运行结果
===== 正常场景 ===== 【静态代理-前置】开始调用addUser方法,参数:username=张三, age=25 【核心逻辑】新增用户:张三,年龄:25 【静态代理-后置】addUser方法调用成功,返回结果:true 【静态代理-耗时】addUser方法执行耗时:1ms ===== 异常场景 ===== 【静态代理-前置】开始调用addUser方法,参数:username=, age=20 【静态代理-异常】addUser方法调用失败,异常信息:用户名不能为空 【静态代理-耗时】addUser方法执行耗时:0ms 客户端捕获异常:用户名不能为空

2.3 静态代理的优缺点

优点
  • 实现简单:纯原生 Java 实现,无需依赖任何框架,新手易理解;
  • 性能最优:编译期确定代理逻辑,无反射、无字节码生成开销;
  • 逻辑清晰:代理类与目标类一一对应,调试时可直接定位代码。
缺点
  • 代码冗余:每一个目标类都需要编写对应的代理类,若系统中有 100 个服务类,就需要 100 个代理类;
  • 维护成本高:若抽象主题接口新增 / 修改方法,所有代理类都需同步修改;
  • 扩展性差:代理逻辑无法复用,不同目标类的附加逻辑(如日志)需重复编写。

2.4 静态代理的适用场景

仅适用于目标类数量极少、业务逻辑固定、无需频繁扩展的简单场景,如小型工具类、固定流程的业务模块,实际企业开发中使用频率极低。

三、JDK 动态代理:基于接口的 “通用代理”

为解决静态代理的代码冗余问题,Java 提供了原生的动态代理机制 ——JDK 动态代理。代理类无需手动编写,而是在运行时通过反射动态生成,可代理所有实现了接口的目标类,实现 “一套代理逻辑适配所有目标类”。

3.1 核心原理

JDK 动态代理的核心依赖java.lang.reflect包下的两个类 / 接口:

  • Proxy:核心工具类,通过newProxyInstance()方法动态生成代理类的字节码,并创建代理对象;
  • InvocationHandler:调用处理器接口,所有代理方法的逻辑都会委托给该接口的invoke()方法处理。

其底层逻辑可概括为:

  1. 代理类由Proxy类动态生成,继承自java.lang.reflect.Proxy,并实现目标类的所有接口;
  2. 代理类的所有接口方法都会调用InvocationHandlerinvoke()方法;
  3. invoke()方法中,开发者可统一处理前置、后置、异常逻辑,并通过反射调用目标方法;
  4. 由于 Java 单继承限制(代理类已继承Proxy),JDK 动态代理只能代理实现了接口的类

3.2 核心 API 详解

类 / 接口核心方法参数说明
ProxynewProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)-loader:目标对象的类加载器;-interfaces:目标对象实现的所有接口;-h:调用处理器(核心逻辑)
InvocationHandlerinvoke(Object proxy, Method method, Object[] args)-proxy:生成的代理对象(一般不使用);-method:当前调用的目标方法;-args:目标方法的参数数组;返回值:目标方法的执行结果

3.3 实战案例:通用日志动态代理

实现一个通用的 JDK 动态代理工具,可给任意实现了接口的目标类添加日志和性能监控功能。

步骤 1:编写通用调用处理器
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.text.SimpleDateFormat; import java.util.Date; /** * 通用JDK动态代理调用处理器 * 统一处理所有代理方法的日志、性能监控逻辑 */ public class JdkLogInvocationHandler implements InvocationHandler { // 持有目标对象引用(通用类型,适配所有目标类) private final Object target; public JdkLogInvocationHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 1. 前置逻辑:日志记录(含时间戳) SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String methodName = method.getName(); System.out.println("【JDK动态代理-" + sdf.format(new Date()) + "】开始调用方法:" + methodName); System.out.println("【JDK动态代理】方法参数:" + argsToString(args)); long startTime = System.currentTimeMillis(); Object result = null; try { // 2. 调用目标对象的核心方法(反射) result = method.invoke(target, args); // 3. 后置逻辑:调用成功日志 System.out.println("【JDK动态代理-" + sdf.format(new Date()) + "】方法" + methodName + "调用成功,返回结果:" + result); return result; } catch (Exception e) { // 4. 异常逻辑:调用失败日志(解包原始异常) Throwable realException = e.getTargetException() == null ? e : e.getTargetException(); System.out.println("【JDK动态代理-" + sdf.format(new Date()) + "】方法" + methodName + "调用失败,异常:" + realException.getMessage()); throw realException; // 抛出原始异常,避免包装 } finally { // 5. 收尾逻辑:性能监控 long endTime = System.currentTimeMillis(); System.out.println("【JDK动态代理】方法" + methodName + "执行耗时:" + (endTime - startTime) + "ms\n"); } } /** * 参数数组转字符串,方便日志打印 */ private String argsToString(Object[] args) { if (args == null || args.length == 0) { return "无参数"; } StringBuilder sb = new StringBuilder(); for (int i = 0; i < args.length; i++) { sb.append("arg").append(i + 1).append("=").append(args[i]); if (i < args.length - 1) { sb.append(", "); } } return sb.toString(); } }
步骤 2:编写 JDK 动态代理工具类
import java.lang.reflect.Proxy; /** * JDK动态代理工具类 * 提供通用的代理对象生成方法 */ public class JdkProxyFactory { /** * 生成目标对象的代理对象 * @param target 目标对象(必须实现至少一个接口) * @param <T> 目标对象类型 * @return 代理对象 */ @SuppressWarnings("unchecked") public static <T> T createProxy(T target) { // 1. 获取目标对象的类加载器 ClassLoader classLoader = target.getClass().getClassLoader(); // 2. 获取目标对象实现的所有接口 Class<?>[] interfaces = target.getClass().getInterfaces(); // 3. 创建调用处理器 JdkLogInvocationHandler handler = new JdkLogInvocationHandler(target); // 4. 动态生成代理对象并返回 return (T) Proxy.newProxyInstance(classLoader, interfaces, handler); } }
步骤 3:客户端测试(复用 UserService 体系)
/** * 客户端:测试JDK动态代理 */ public class JdkProxyClient { public static void main(String[] args) { // 1. 创建目标对象(实现了接口) UserService target = new UserServiceImpl(); // 2. 生成动态代理对象 UserService proxy = JdkProxyFactory.createProxy(target); // 3. 调用代理方法(正常场景) System.out.println("===== 正常场景 ====="); proxy.addUser("李四", 30); // 4. 新增测试:代理另一类方法(验证通用性) System.out.println("===== 多类适配 ====="); OrderService orderTarget = new OrderServiceImpl(); OrderService orderProxy = JdkProxyFactory.createProxy(orderTarget); orderProxy.createOrder("ORDER_001", 100.0); } // 新增订单服务接口(验证通用性) interface OrderService { boolean createOrder(String orderNo, double amount); } // 订单服务实现类 static class OrderServiceImpl implements OrderService { @Override public boolean createOrder(String orderNo, double amount) { System.out.println("【核心逻辑】创建订单:" + orderNo + ",金额:" + amount); return true; } } }
运行结果
===== 正常场景 ===== 【JDK动态代理-2026-03-11 16:00:00】开始调用方法:addUser 【JDK动态代理】方法参数:arg1=李四, arg2=30 【核心逻辑】新增用户:李四,年龄:30 【JDK动态代理-2026-03-11 16:00:00】方法addUser调用成功,返回结果:true 【JDK动态代理】方法addUser执行耗时:1ms ===== 多类适配 ===== 【JDK动态代理-2026-03-11 16:00:00】开始调用方法:createOrder 【JDK动态代理】方法参数:arg1=ORDER_001, arg2=100.0 【核心逻辑】创建订单:ORDER_001,金额:100.0 【JDK动态代理-2026-03-11 16:00:00】方法createOrder调用成功,返回结果:true 【JDK动态代理】方法createOrder执行耗时:0ms

3.4 JDK 动态代理的优缺点

优点
  • 通用性强:一套代理逻辑可适配所有实现接口的目标类,无代码冗余;
  • 扩展性好:新增目标类无需修改代理逻辑,只需传入目标对象即可;
  • 原生支持:基于 JDK 原生 API 实现,无需依赖第三方框架。
缺点
  • 接口限制:只能代理实现了接口的类,无法代理普通类(无接口);
  • 继承限制:代理类继承自Proxy,无法代理final类;
  • 反射开销:目标方法调用基于反射实现,性能略低于静态代理(现代 JVM 优化后,该开销可忽略)。

3.5 JDK 动态代理的适用场景

是企业开发中最常用的代理方式,适用于目标类实现了接口的所有场景,如 Spring AOP 对接口型 Bean 的代理、MyBatis Mapper 接口代理、RPC 接口代理等。

四、CGLIB 动态代理:基于继承的 “无接口代理”

JDK 动态代理的核心限制是 “必须实现接口”,而在实际开发中,很多业务类并未实现接口(如普通 POJO、工具类)。CGLIB(Code Generation Library)作为第三方字节码生成库,通过继承目标类生成子类的方式实现代理,突破了接口限制。

4.1 核心原理

CGLIB 基于 ASM 字节码操作框架,其核心原理为:

  1. 在运行时动态生成目标类的子类作为代理类;
  2. 代理类重写目标类的所有非final、非private方法;
  3. 通过MethodInterceptor(方法拦截器)拦截所有重写方法的调用;
  4. 在拦截器中处理附加逻辑,并调用目标类的原始方法。

核心特点:

  • 无需目标类实现接口,直接代理普通类;
  • 代理类继承目标类,因此无法代理final类(无法继承),也无法代理final方法(无法重写);
  • 方法调用通过字节码直接调用,性能优于 JDK 动态代理(Spring 5 后已优化,两者性能差异极小)。

4.2 核心依赖与 API

依赖引入(Maven)

CGLIB 非 JDK 原生库,需手动引入依赖(Spring Core 已内置 CGLIB,Spring 项目无需额外引入):

<dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.3.0</version> </dependency>
核心 API 详解
类 / 接口核心方法作用
EnhancersetSuperclass(Class<?> superclass)setCallback(Callback callback)create()核心增强类,用于生成代理类:- 设置目标类为父类;- 设置回调拦截器;- 生成代理对象
MethodInterceptorintercept(Object obj, Method method, Object[] args, MethodProxy proxy)方法拦截器,处理所有代理方法逻辑:-obj:代理对象;-method:目标方法;-args:方法参数;-proxy:方法代理(高效调用父类方法)
MethodProxyinvokeSuper(Object obj, Object[] args)调用父类(目标类)的原始方法,性能优于反射method.invoke()

4.3 实战案例:CGLIB 通用代理工具

实现一个通用的 CGLIB 代理工具,代理无接口的普通类。

步骤 1:编写 CGLIB 方法拦截器
import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; import java.text.SimpleDateFormat; import java.util.Date; /** * CGLIB方法拦截器 * 统一处理代理方法的日志、性能监控逻辑 */ public class CglibLogInterceptor implements MethodInterceptor { @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { // 1. 前置逻辑:日志记录 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String methodName = method.getName(); System.out.println("【CGLIB动态代理-" + sdf.format(new Date()) + "】开始调用方法:" + methodName); System.out.println("【CGLIB动态代理】方法参数:" + argsToString(args)); long startTime = System.currentTimeMillis(); Object result = null; try { // 2. 调用目标类的原始方法(高效调用) result = proxy.invokeSuper(obj, args); // 3. 后置逻辑:调用成功日志 System.out.println("【CGLIB动态代理-" + sdf.format(new Date()) + "】方法" + methodName + "调用成功,返回结果:" + result); return result; } catch (Exception e) { // 4. 异常逻辑:调用失败日志 System.out.println("【CGLIB动态代理-" + sdf.format(new Date()) + "】方法" + methodName + "调用失败,异常:" + e.getMessage()); throw e; } finally { // 5. 收尾逻辑:性能监控 long endTime = System.currentTimeMillis(); System.out.println("【CGLIB动态代理】方法" + methodName + "执行耗时:" + (endTime - startTime) + "ms\n"); } } /** * 参数数组转字符串 */ private String argsToString(Object[] args) { if (args == null || args.length == 0) { return "无参数"; } StringBuilder sb = new StringBuilder(); for (int i = 0; i < args.length; i++) { sb.append("arg").append(i + 1).append("=").append(args[i]); if (i < args.length - 1) { sb.append(", "); } } return sb.toString(); } }
步骤 2:编写 CGLIB 代理工厂
import net.sf.cglib.proxy.Enhancer; /** * CGLIB动态代理工厂 * 生成无接口类的代理对象 */ public class CglibProxyFactory { /** * 生成代理对象 * @param targetClass 目标类的Class对象 * @param <T> 目标类类型 * @return 代理对象 */ @SuppressWarnings("unchecked") public static <T> T createProxy(Class<T> targetClass) { // 1. 创建增强器 Enhancer enhancer = new Enhancer(); // 2. 设置父类(目标类) enhancer.setSuperclass(targetClass); // 3. 设置方法拦截器 enhancer.setCallback(new CglibLogInterceptor()); // 4. 生成并返回代理对象 return (T) enhancer.create(); } }
步骤 3:客户端测试(代理无接口类)
/** * 客户端:测试CGLIB动态代理 */ public class CglibProxyClient { public static void main(String[] args) { // 1. 代理无接口的普通类 System.out.println("===== 代理无接口类 ====="); PayService payProxy = CglibProxyFactory.createProxy(PayService.class); payProxy.pay("USER_001", 200.5); // 2. 测试final方法(无法代理) System.out.println("===== 测试final方法 ====="); payProxy.finalMethod(); } /** * 无接口的普通类(支付服务) */ static class PayService { // 普通方法(可被代理) public boolean pay(String userId, double amount) { System.out.println("【核心逻辑】用户" + userId + "支付金额:" + amount); return true; } // final方法(无法被代理) public final void finalMethod() { System.out.println("【核心逻辑】这是final方法,无法被CGLIB代理增强"); } } }
运行结果

plaintext

===== 代理无接口类 ===== 【CGLIB动态代理-2026-03-11 16:30:00】开始调用方法:pay 【CGLIB动态代理】方法参数:arg1=USER_001, arg2=200.5 【核心逻辑】用户USER_001支付金额:200.5 【CGLIB动态代理-2026-03-11 16:30:00】方法pay调用成功,返回结果:true 【CGLIB动态代理】方法pay执行耗时:1ms ===== 测试final方法 ===== 【核心逻辑】这是final方法,无法被CGLIB代理增强

4.4 CGLIB 动态代理的优缺点

优点
  • 无接口限制:可代理任意非final普通类,弥补 JDK 动态代理的不足;
  • 性能更优:通过字节码直接调用方法,性能略优于 JDK 动态代理;
  • 功能丰富:支持方法拦截、构造器拦截、回调过滤等高级功能。
缺点
  • 依赖第三方库:需引入 CGLIB/ASM 依赖(Spring 项目可忽略);
  • 继承限制:无法代理final类和final方法;
  • 初始化开销:动态生成字节码的初始化开销略高于 JDK 动态代理(运行时可忽略)。

4.5 CGLIB 动态代理的适用场景

适用于目标类未实现接口的场景,如 Spring AOP 对非接口型 Bean 的代理、MyBatis 延迟加载、Hibernate 实体代理等。

五、三种代理模式的核心对比(面试必背)

特性静态代理JDK 动态代理CGLIB 动态代理
实现方式手动编写代理类反射 + 接口字节码生成 + 继承
是否需要接口
代理类生成时机编译期运行时运行时
核心限制无(但代码冗余)只能代理接口类不能代理 final 类 / 方法
性能最优(无额外开销)中等(反射开销)高(字节码直接调用)
代码冗余度极高(一对一)极低(通用代理)极低(通用代理)
维护成本高(接口修改需同步改)低(通用逻辑)低(通用逻辑)
Spring 默认使用不使用有接口时优先使用无接口时使用

六、代理模式与 AOP 的关系

6.1 AOP 的核心本质

AOP(面向切面编程)的核心是 “横切逻辑”:将日志、事务、权限等与核心业务无关的逻辑(横切逻辑)从业务代码中抽离,通过 “切面” 统一管理。而动态代理是 AOP 实现的底层技术

6.2 Spring AOP 的代理策略

Spring AOP 自动选择代理方式:

  1. 若目标 Bean 实现了接口,默认使用JDK 动态代理
  2. 若目标 Bean 未实现接口,使用CGLIB 代理
  3. 可通过proxy-target-class=true强制使用 CGLIB 代理。

6.3 示例:Spring AOP 底层代理逻辑

// Spring AOP 核心拦截器(简化版) public class AopAdviceInterceptor implements MethodInterceptor { private final Advice advice; // 切面逻辑(如@Before、@After) private final TargetSource targetSource; // 目标对象 @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { // 1. 执行前置通知(@Before) advice.before(method, args); try { // 2. 调用目标方法 Object result = targetSource.getTarget().getClass().getMethod(method.getName(), method.getParameterTypes()).invoke(targetSource.getTarget(), args); // 3. 执行后置通知(@AfterReturning) advice.afterReturning(result); return result; } catch (Exception e) { // 4. 执行异常通知(@AfterThrowing) advice.afterThrowing(e); throw e; } finally { // 5. 执行最终通知(@After) advice.after(); } } }

七、总结

  1. 代理模式的核心:通过代理对象封装目标对象,实现核心逻辑与附加逻辑的解耦,核心是 “增强不修改”;
  2. 静态代理:简单但冗余,仅适用于简单固定场景;
  3. JDK 动态代理:基于接口,原生支持,是接口型 Bean 的首选;
  4. CGLIB 动态代理:基于继承,突破接口限制,适配无接口类;
  5. 动态代理是 AOP 的底层:Spring AOP、事务、日志等功能均依赖动态代理实现。

掌握 Java 代理的实现原理,不仅能理解设计模式的实战价值,更能打通 Spring 框架的底层逻辑,是 Java 后端开发者的核心基本功。

http://www.jsqmd.com/news/471600/

相关文章:

  • Protocol Launcher 系列:Kaleidoscope 优雅的代码比对与合并
  • __try / __except 和 __try / __finally 用法(五)
  • 鸿蒙中 memory://协议
  • PHP编写对账脚本:立即开发一个每分钟运行的 PHP 脚本,比对活跃商品的 DB 和 Redis 库存。
  • MYSQL中锁的分类与加锁方式小结
  • 鸿蒙开发工程师:构建未来智能生态的基石——技术解析、能力要求与面试指南
  • 2026年伽玛能谱仪采购必看:这些知名企业的产品值得关注 - 品牌推荐大师1
  • Linux驱动SPI-3-注册流程spi4
  • 势能法求解含齿根裂纹的直齿轮时变啮合刚度,根据万志国和梁新辉文献并结合其它文献采用MATLAB...
  • 高性能后台服务分级优化--百万级IO、千万级内存、亿级CPU的递进式优化思路
  • HarmonyOS开发指南:从入门到精通——聚焦APP、游戏与PC应用
  • 告别“塑料二次元”: 2D 角色 PBR 材质化与光追重构工作流
  • 换道轨迹预测:用LSTM模型捕捉车辆的“思考“过程
  • 复试第十一天
  • 【C++】lock_guard 与 unique_lock
  • 别再用串口屏蹲车间了!WPF .NET 8上位机实战:自定义仪表盘+LiveCharts2趋势图+SignalR远程运维,附6个工业级踩坑指南
  • 支付宝立减金回收黑科技!不用消费也能把钱揣进口袋 - 可可收
  • 基于ATP仿真建模的35kV与110kV变压器PT谐振过电压问题研究
  • PHP的多个账号使用同一手机号,收货地址怎么同步?
  • LabVIEW打造超酷液压泵试验台程序:功能全解析
  • 分析2026年江苏口碑不错的液氧、高纯氮、标准气工业气体厂家 - 工业品网
  • 做了8年工业上位机,我开源了这套通用框架!多设备/多协议10分钟快速对接,开箱可商用
  • 电网同步这事儿听着玄乎,其实就像给三相交流电装个节拍器。传统锁相环遇到电压波动就哆嗦,今天咱们聊点硬核的——怎么用d轴电压归一化让这个节拍器稳如老狗
  • 拒绝“实景贴皮感”:2D 角色摄影级实景融合与动态投射工作流
  • 用COMSOL拆解变电站的电场分布:从高压柜到电缆的实战指南
  • 西门子S7 - 1500博图程序在大型生产线中的实战例程分享
  • 北京/上海/深圳/杭州/南京/无锡高端腕表维修科普:品牌故障解析+正规门店指引 - 时光修表匠
  • 光伏储能微电网系统设计与实现
  • 【LLM进阶-RAG】2.切片算法策略
  • 分析初中毕业选学校服务,合肥南亚理工学校性价比高吗 - mypinpai