CGLIb 创建代理

  • 创建回调
  • 创建代理(通过增强器和回调接口)
    • 设置回调
    • CGLib总结
      • 代理对象通过继承目标对象来封装目标对象的实现
      • CGlib 拦截的实现——在执行目标方法前判断拦截器是否存在并拦截

创建回调


创建代理(通过增强器和回调接口)

设置回调


这个proxyInstance就是我们的代理对象

代理对象对象通过实现接口Factory的setCallBack方法

那么代理对象究竟是如何实现该方法的,我们以UserServiceImpl代理对象为例,并且展开拦截的实现原理

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//package com.example.tran.service.impl;import java.lang.reflect.Method;
import org.aopalliance.aop.Advice;
import org.springframework.aop.Advisor;
import org.springframework.aop.SpringProxy;
import org.springframework.aop.TargetClassAware;
import org.springframework.aop.TargetSource;
import org.springframework.aop.framework.Advised;
import org.springframework.aop.framework.AopConfigException;
import org.springframework.cglib.core.ReflectUtils;
import org.springframework.cglib.core.Signature;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.Dispatcher;
import org.springframework.cglib.proxy.Factory;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import org.springframework.cglib.proxy.NoOp;public class UserServiceImpl$$EnhancerBySpringCGLIB$$b2af7d61 extends UserServiceImpl implements SpringProxy, Advised, Factory {private boolean CGLIB$BOUND;public static Object CGLIB$FACTORY_DATA;private static final ThreadLocal CGLIB$THREAD_CALLBACKS;private static final Callback[] CGLIB$STATIC_CALLBACKS;private MethodInterceptor CGLIB$CALLBACK_0;private MethodInterceptor CGLIB$CALLBACK_1;private NoOp CGLIB$CALLBACK_2;private Dispatcher CGLIB$CALLBACK_3;private Dispatcher CGLIB$CALLBACK_4;private MethodInterceptor CGLIB$CALLBACK_5;private MethodInterceptor CGLIB$CALLBACK_6;private static Object CGLIB$CALLBACK_FILTER;private static final Method CGLIB$accountStar$0$Method;private static final MethodProxy CGLIB$accountStar$0$Proxy;private static final Object[] CGLIB$emptyArgs;private static final Method CGLIB$accountMoney$1$Method;private static final MethodProxy CGLIB$accountMoney$1$Proxy;private static final Method CGLIB$equals$2$Method;private static final MethodProxy CGLIB$equals$2$Proxy;private static final Method CGLIB$toString$3$Method;private static final MethodProxy CGLIB$toString$3$Proxy;private static final Method CGLIB$hashCode$4$Method;private static final MethodProxy CGLIB$hashCode$4$Proxy;private static final Method CGLIB$clone$5$Method;private static final MethodProxy CGLIB$clone$5$Proxy;static void CGLIB$STATICHOOK10() {CGLIB$THREAD_CALLBACKS = new ThreadLocal();CGLIB$emptyArgs = new Object[0];Class var0 = Class.forName("com.example.tran.service.impl.UserServiceImpl$$EnhancerBySpringCGLIB$$b2af7d61");Class var1;Method[] var10000 = ReflectUtils.findMethods(new String[]{"equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"}, (var1 = Class.forName("java.lang.Object")).getDeclaredMethods());CGLIB$equals$2$Method = var10000[0];CGLIB$equals$2$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$2");CGLIB$toString$3$Method = var10000[1];CGLIB$toString$3$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$3");CGLIB$hashCode$4$Method = var10000[2];CGLIB$hashCode$4$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$4");CGLIB$clone$5$Method = var10000[3];CGLIB$clone$5$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$5");var10000 = ReflectUtils.findMethods(new String[]{"accountStar", "()V", "accountMoney", "()V"}, (var1 = Class.forName("com.example.tran.service.impl.UserServiceImpl")).getDeclaredMethods());CGLIB$accountStar$0$Method = var10000[0];CGLIB$accountStar$0$Proxy = MethodProxy.create(var1, var0, "()V", "accountStar", "CGLIB$accountStar$0");CGLIB$accountMoney$1$Method = var10000[1];CGLIB$accountMoney$1$Proxy = MethodProxy.create(var1, var0, "()V", "accountMoney", "CGLIB$accountMoney$1");}final void CGLIB$accountStar$0() {super.accountStar();}public final void accountStar() {MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_0;}if (var10000 != null) {var10000.intercept(this, CGLIB$accountStar$0$Method, CGLIB$emptyArgs, CGLIB$accountStar$0$Proxy);} else {super.accountStar();}}final void CGLIB$accountMoney$1() {super.accountMoney();}public final void accountMoney() {MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_0;}if (var10000 != null) {var10000.intercept(this, CGLIB$accountMoney$1$Method, CGLIB$emptyArgs, CGLIB$accountMoney$1$Proxy);} else {super.accountMoney();}}final boolean CGLIB$equals$2(Object var1) {return super.equals(var1);}public final boolean equals(Object var1) {MethodInterceptor var10000 = this.CGLIB$CALLBACK_5;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_5;}if (var10000 != null) {Object var2 = var10000.intercept(this, CGLIB$equals$2$Method, new Object[]{var1}, CGLIB$equals$2$Proxy);return var2 == null ? false : (Boolean)var2;} else {return super.equals(var1);}}final String CGLIB$toString$3() {return super.toString();}public final String toString() {MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_0;}return var10000 != null ? (String)var10000.intercept(this, CGLIB$toString$3$Method, CGLIB$emptyArgs, CGLIB$toString$3$Proxy) : super.toString();}final int CGLIB$hashCode$4() {return super.hashCode();}public final int hashCode() {MethodInterceptor var10000 = this.CGLIB$CALLBACK_6;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_6;}if (var10000 != null) {Object var1 = var10000.intercept(this, CGLIB$hashCode$4$Method, CGLIB$emptyArgs, CGLIB$hashCode$4$Proxy);return var1 == null ? 0 : ((Number)var1).intValue();} else {return super.hashCode();}}final Object CGLIB$clone$5() throws CloneNotSupportedException {return super.clone();}protected final Object clone() throws CloneNotSupportedException {MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_0;}return var10000 != null ? var10000.intercept(this, CGLIB$clone$5$Method, CGLIB$emptyArgs, CGLIB$clone$5$Proxy) : super.clone();}public static MethodProxy CGLIB$findMethodProxy(Signature var0) {String var10000 = var0.toString();switch(var10000.hashCode()) {case -1179333386:if (var10000.equals("accountStar()V")) {return CGLIB$accountStar$0$Proxy;}break;case -508378822:if (var10000.equals("clone()Ljava/lang/Object;")) {return CGLIB$clone$5$Proxy;}break;case 448476162:if (var10000.equals("accountMoney()V")) {return CGLIB$accountMoney$1$Proxy;}break;case 1826985398:if (var10000.equals("equals(Ljava/lang/Object;)Z")) {return CGLIB$equals$2$Proxy;}break;case 1913648695:if (var10000.equals("toString()Ljava/lang/String;")) {return CGLIB$toString$3$Proxy;}break;case 1984935277:if (var10000.equals("hashCode()I")) {return CGLIB$hashCode$4$Proxy;}}return null;}public final int indexOf(Advisor var1) {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).indexOf(var1);}public final int indexOf(Advice var1) {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).indexOf(var1);}public final boolean isFrozen() {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).isFrozen();}public final Class[] getProxiedInterfaces() {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).getProxiedInterfaces();}public final boolean isInterfaceProxied(Class var1) {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).isInterfaceProxied(var1);}public final String toProxyConfigString() {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).toProxyConfigString();}public final boolean isProxyTargetClass() {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).isProxyTargetClass();}public final boolean isExposeProxy() {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).isExposeProxy();}public final void setPreFiltered(boolean var1) {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}((Advised)var10000.loadObject()).setPreFiltered(var1);}public final void setTargetSource(TargetSource var1) {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}((Advised)var10000.loadObject()).setTargetSource(var1);}public final boolean isPreFiltered() {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).isPreFiltered();}public final TargetSource getTargetSource() {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).getTargetSource();}public final void setExposeProxy(boolean var1) {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}((Advised)var10000.loadObject()).setExposeProxy(var1);}public final Advisor[] getAdvisors() {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).getAdvisors();}public final void addAdvisor(Advisor var1) throws AopConfigException {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}((Advised)var10000.loadObject()).addAdvisor(var1);}public final void addAdvisor(int var1, Advisor var2) throws AopConfigException {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}((Advised)var10000.loadObject()).addAdvisor(var1, var2);}public final void removeAdvisor(int var1) throws AopConfigException {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}((Advised)var10000.loadObject()).removeAdvisor(var1);}public final boolean removeAdvisor(Advisor var1) {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).removeAdvisor(var1);}public final boolean removeAdvice(Advice var1) {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).removeAdvice(var1);}public final boolean replaceAdvisor(Advisor var1, Advisor var2) throws AopConfigException {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).replaceAdvisor(var1, var2);}public final void addAdvice(int var1, Advice var2) throws AopConfigException {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}((Advised)var10000.loadObject()).addAdvice(var1, var2);}public final void addAdvice(Advice var1) throws AopConfigException {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}((Advised)var10000.loadObject()).addAdvice(var1);}public final Class getTargetClass() {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((TargetClassAware)var10000.loadObject()).getTargetClass();}public UserServiceImpl$$EnhancerBySpringCGLIB$$b2af7d61() {CGLIB$BIND_CALLBACKS(this);}public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) {CGLIB$THREAD_CALLBACKS.set(var0);}public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] var0) {CGLIB$STATIC_CALLBACKS = var0;}private static final void CGLIB$BIND_CALLBACKS(Object var0) {UserServiceImpl$$EnhancerBySpringCGLIB$$b2af7d61 var1 = (UserServiceImpl$$EnhancerBySpringCGLIB$$b2af7d61)var0;if (!var1.CGLIB$BOUND) {var1.CGLIB$BOUND = true;Object var10000 = CGLIB$THREAD_CALLBACKS.get();if (var10000 == null) {var10000 = CGLIB$STATIC_CALLBACKS;if (var10000 == null) {return;}}Callback[] var10001 = (Callback[])var10000;var1.CGLIB$CALLBACK_6 = (MethodInterceptor)((Callback[])var10000)[6];var1.CGLIB$CALLBACK_5 = (MethodInterceptor)var10001[5];var1.CGLIB$CALLBACK_4 = (Dispatcher)var10001[4];var1.CGLIB$CALLBACK_3 = (Dispatcher)var10001[3];var1.CGLIB$CALLBACK_2 = (NoOp)var10001[2];var1.CGLIB$CALLBACK_1 = (MethodInterceptor)var10001[1];var1.CGLIB$CALLBACK_0 = (MethodInterceptor)var10001[0];}}public Object newInstance(Callback[] var1) {CGLIB$SET_THREAD_CALLBACKS(var1);UserServiceImpl$$EnhancerBySpringCGLIB$$b2af7d61 var10000 = new UserServiceImpl$$EnhancerBySpringCGLIB$$b2af7d61();CGLIB$SET_THREAD_CALLBACKS((Callback[])null);return var10000;}public Object newInstance(Callback var1) {throw new IllegalStateException("More than one callback object required");}public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {CGLIB$SET_THREAD_CALLBACKS(var3);UserServiceImpl$$EnhancerBySpringCGLIB$$b2af7d61 var10000 = new UserServiceImpl$$EnhancerBySpringCGLIB$$b2af7d61;switch(var1.length) {case 0:var10000.<init>();CGLIB$SET_THREAD_CALLBACKS((Callback[])null);return var10000;default:throw new IllegalArgumentException("Constructor not found");}}public Callback getCallback(int var1) {CGLIB$BIND_CALLBACKS(this);Object var10000;switch(var1) {case 0:var10000 = this.CGLIB$CALLBACK_0;break;case 1:var10000 = this.CGLIB$CALLBACK_1;break;case 2:var10000 = this.CGLIB$CALLBACK_2;break;case 3:var10000 = this.CGLIB$CALLBACK_3;break;case 4:var10000 = this.CGLIB$CALLBACK_4;break;case 5:var10000 = this.CGLIB$CALLBACK_5;break;case 6:var10000 = this.CGLIB$CALLBACK_6;break;default:var10000 = null;}return (Callback)var10000;}public void setCallback(int var1, Callback var2) {switch(var1) {case 0:this.CGLIB$CALLBACK_0 = (MethodInterceptor)var2;break;case 1:this.CGLIB$CALLBACK_1 = (MethodInterceptor)var2;break;case 2:this.CGLIB$CALLBACK_2 = (NoOp)var2;break;case 3:this.CGLIB$CALLBACK_3 = (Dispatcher)var2;break;case 4:this.CGLIB$CALLBACK_4 = (Dispatcher)var2;break;case 5:this.CGLIB$CALLBACK_5 = (MethodInterceptor)var2;break;case 6:this.CGLIB$CALLBACK_6 = (MethodInterceptor)var2;}}public Callback[] getCallbacks() {CGLIB$BIND_CALLBACKS(this);return new Callback[]{this.CGLIB$CALLBACK_0, this.CGLIB$CALLBACK_1, this.CGLIB$CALLBACK_2, this.CGLIB$CALLBACK_3, this.CGLIB$CALLBACK_4, this.CGLIB$CALLBACK_5, this.CGLIB$CALLBACK_6};}public void setCallbacks(Callback[] var1) {this.CGLIB$CALLBACK_0 = (MethodInterceptor)var1[0];this.CGLIB$CALLBACK_1 = (MethodInterceptor)var1[1];this.CGLIB$CALLBACK_2 = (NoOp)var1[2];this.CGLIB$CALLBACK_3 = (Dispatcher)var1[3];this.CGLIB$CALLBACK_4 = (Dispatcher)var1[4];this.CGLIB$CALLBACK_5 = (MethodInterceptor)var1[5];this.CGLIB$CALLBACK_6 = (MethodInterceptor)var1[6];}static {CGLIB$STATICHOOK10();}
}

CGLib总结

代理对象通过继承目标对象来封装目标对象的实现


CGlib 拦截的实现——在执行目标方法前判断拦截器是否存在并拦截

可以看到,先执行拦截,再执行targetClass.method这一过程(通过super.method来实现)

CGLIb 创建代理相关推荐

  1. 使用cglib创建代理对象

    在上一篇文章中,我讨论了基于标准Java的代理对象. 当您要在实现接口的对象上具有方法调用处理程序时,可以使用这些方法. Java反射代理的创建要求您具有一个实现接口的对象. 我们要代理的对象已经失控 ...

  2. cglib创建代理对象(1)

    cglib创建代理对象 还是从一个的小demo开始 例子 被代理的类 public class Bean{public String sayHello(String name) {return &qu ...

  3. Spring AOP 源码分析 - 创建代理对象

    1.简介 在上一篇文章中,我分析了 Spring 是如何为目标 bean 筛选合适的通知器的.现在通知器选好了,接下来就要通过代理的方式将通知器(Advisor)所持有的通知(Advice)织入到 b ...

  4. 使用djcproxy创建代理对象

    在过去的几周中,我展示了如何使用Java Reflection API和cglib创建代理对象. 在本文中,我将向您展示如何使用djcproxy做到这一点. 哦,不是,另一个代理实现! 除了我创建此代 ...

  5. Spring AOP源码(2)—AspectJAwareAdvisorAutoProxyCreator创建代理对象【两万字】

      基于最新Spring 5.x,介绍了Spring AOP中的AspectJAwareAdvisorAutoProxyCreator自动代理创建者的工作流程,对于创建代理对象的源码进行了深度分析! ...

  6. Spring AOP之---基于JDK动态代理和CGLib动态代理的AOP实现

    AOP(面向切面编程)是OOP的有益补充,它只适合那些具有横切逻辑的应用场合,如性能监测,访问控制,事物管理,日志记录等.至于怎么理解横切逻辑,敲完实例代码也就明白了. 为什么要使用AOP,举个栗子: ...

  7. 你必须会的 JDK 动态代理和 CGLIB 动态代理

    来自:ytao 我们在阅读一些 Java 框架的源码时,基本上常会看到使用动态代理机制,它可以无感的对既有代码进行方法的增强,使得代码拥有更好的拓展性.通过从静态代理.JDK 动态代理.CGLIB 动 ...

  8. 代理详解 静态代理+JDK/CGLIB 动态代理实战

    1. 代理模式 代理模式是一种比较好理解的设计模式.简单来说就是 我们使用代理对象来代替对真实对象(real object)的访问,这样就可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对 ...

  9. 深入理解Java Proxy和CGLIB动态代理原理

    点击上方关注,每天进步一点点 动态代理在Java中有着广泛的应用,比如Spring AOP,Hibernate数据查询.测试框架的后端mock.RPC,Java注解对象获取等.静态代理的代理关系在编译 ...

最新文章

  1. 【 MATLAB 】Contour plot of matrix(矩阵的等高线图)
  2. leetcode 144. Binary Tree Preorder Traversal
  3. 信息源按加工深度划分_铝合金插铣加工切削力分析及成屑弧区划分
  4. 注册刷短信验证码的问题
  5. android获取本地图片后缀,Android向图片文件添加扩展信息EXIF如地点,时间,人物等...
  6. 快速删除数据库中所有表中的数据
  7. 转置与变换(Transposes and Permutation)
  8. SpringBoot-Mail 发邮件(单发、群发、加附件、HTML格式)
  9. linux中ps ef和aux,Linux中ps aux、ps -aux、ps -ef之间的区别讲解
  10. oracle中自定义异常编号,Oracle自定义异常的使用
  11. 【洛谷P2279】[HNOI2003]消防局的设立
  12. 考研英语作文:环保呼吁信
  13. 运筹学那些事,专科学生学习运筹学之运输问题,No.5
  14. 拆机专用磁力桌垫:保证一颗螺丝也不漏网
  15. 1. 用户行为采集平台概述
  16. 华为云CDN,是怎样拯救你的等待焦虑症
  17. 对于效率施工作业出力的另一途径采用路缘石滑模机
  18. EMC设计分析方法与风险评估技术
  19. 游戏人生Silverlight(3) - 打苍蝇[Silverlight 2.0(c#)]
  20. 2021年美容师(中级)考试试卷及美容师(中级)模拟考试

热门文章

  1. 关于hi3516ev100调试zbar二维码和链接wifi问题
  2. ROS安装/// rosdep update/the read operation is timed out
  3. 联想拯救者R7000P加硬盘
  4. NLP聊天机器人的搭建(chatbot)(一)
  5. 逻辑回归logistic原理(python代码实现)
  6. ffmpeg运行在服务器上,如何在脱离流媒体服务器的时候使用ffmpeg 监测.m3u8直播视频流的状态?...
  7. 【86】ASPM进入和退出L1
  8. 服务器被攻击导致CPU100%的解决
  9. Self-supervised
  10. fill()的使用方法