【Spring】GoF 之代理模式

一、代理模式

在 Java 程序中的代理模式的作用:

  • 当一个对象需要受到保护的时候,可以考虑使用代理对象去完成某个行为

  • 需要给某个对象的功能进行功能增强的时候,可以考虑找一个代理进行增强

  • A 对象无法和 B 对象直接交互时,也可以使用代理模式来解决

代理模式中的三大角色:

  • 目标对象(演员)

  • 代理对象(替身演员)

  • 目标对象和代理对象的公共接口(演员与替身演员相同的行为,可以让观众不知道是替身演员)

如果使用代理模式,对于客户端程序来说,客户端是无法察觉的,客户端在使用代理对象的时候就像在使用目标对象

代理模式在代码实现上,包括两种形式:

  • 静态代理

  • 动态代理

 

二、静态代理

package org.qiu.proxy.service;/*** 订单业务接口* @author 秋玄* @version 1.0* @email qiu_2022@aliyun.com* @project Spring* @package org.qiu.proxy.service* @date 2022-11-16-13:09* @since 1.0*/
public interface OrderService {/*** 生成订单*/void generate();/*** 修改订单信息*/void modify();/*** 查看订单详情*/void detail();
}
package org.qiu.proxy.service;/*** @author 秋玄* @version 1.0* @email qiu_2022@aliyun.com* @project Spring* @package org.qiu.proxy.service* @date 2022-11-16-13:10* @since 1.0*/
public class OrderServiceImpl implements OrderService{@Overridepublic void generate() {// 模拟网络延迟try {Thread.sleep(1024);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("订单已生成!");}@Overridepublic void modify() {// 模拟网络延迟try {Thread.sleep(512);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("订单已修改!");}@Overridepublic void detail() {// 模拟网络延迟try {Thread.sleep(800);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("订单详情......");}
}
public class Test {public static void main(String[] args) {OrderService orderService = new OrderServiceImpl();orderService.generate();orderService.detail();orderService.modify();}
}

运行结果:  

项目已上线,并且运行正常,只是客户反馈系统有一些地方运行较慢,要求项目组对系统进行优化。于是项目负责人就下达了这个需求。首先需要搞清楚是哪些业务方法耗时较长,于是让我们统计每个业务方法所耗费的时长。如果是你,你该怎么做呢?

 

第一种方案

直接修改Java源代码,在每个业务方法中添加统计逻辑,如下:

package org.qiu.proxy.service;/*** @author 秋玄* @version 1.0* @email qiu_2022@aliyun.com* @project Spring* @package org.qiu.proxy.service* @date 2022-11-16-13:10* @since 1.0*/
public class OrderServiceImpl implements OrderService{@Overridepublic void generate() {long begin = System.currentTimeMillis();// 模拟网络延迟try {Thread.sleep(1024);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("订单已生成!");long end = System.currentTimeMillis();System.out.println("耗时(毫秒):" + (end - begin));}@Overridepublic void modify() {long begin = System.currentTimeMillis();// 模拟网络延迟try {Thread.sleep(512);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("订单已修改!");long end = System.currentTimeMillis();System.out.println("耗时(毫秒):" + (end - begin));}@Overridepublic void detail() {long begin = System.currentTimeMillis();// 模拟网络延迟try {Thread.sleep(800);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("订单详情......");long end = System.currentTimeMillis();System.out.println("耗时(毫秒):" + (end - begin));}
}

运行效果:  

需求可以满足,但显然是违背了OCP开闭原则,这种方案不可取

第二种方案

编写一个子类继承OrderServiceImpl,在子类中重写每个方法,代码如下:

package org.qiu.proxy.service;/*** @author 秋玄* @version 1.0* @email qiu_2022@aliyun.com* @project Spring* @package org.qiu.proxy.service* @date 2022-11-16-13:24* @since 1.0*/
public class OrderServiceImplSub extends OrderServiceImpl{@Overridepublic void generate() {long begin = System.currentTimeMillis();super.generate();long end = System.currentTimeMillis();System.out.println("耗时(毫秒):" + (end - begin));}@Overridepublic void modify() {long begin = System.currentTimeMillis();super.modify();long end = System.currentTimeMillis();System.out.println("耗时(毫秒):" + (end - begin));}@Overridepublic void detail() {long begin = System.currentTimeMillis();super.detail();long end = System.currentTimeMillis();System.out.println("耗时(毫秒):" + (end - begin));}
}
public class Test {public static void main(String[] args) {OrderService orderService = new OrderServiceImplSub();orderService.generate();orderService.detail();orderService.modify();}
}

运行效果:  

这种方式可以解决,但是存在两个问题:

  • 第一个问题:假设系统中有100个这样的业务类,需要提供100个子类,并且之前写好的创建Service对象的代码,都要修改为创建子类对象

  • 第二个问题:由于采用了继承的方式,导致代码之间的耦合度较高。

这种方案也不可取

第三种方案

使用代理模式(这里采用静态代理)

可以为 OrderService 接口提供一个代理类

package org.qiu.proxy.service;/*** 代理对象* @author 秋玄* @version 1.0* @email qiu_2022@aliyun.com* @project Spring* @package org.qiu.proxy.service* @date 2022-11-16-13:32* @since 1.0*/
public class OrderServiceProxy implements OrderService {// 目标对象// 这里要使用“公共接口”类型,因为公共接口耦合度低private OrderService orderService;// 通过构造方法将目标对象传递给代理对象public OrderServiceProxy(OrderService orderService){this.orderService = orderService;}@Overridepublic void generate() {long begin = System.currentTimeMillis();// 执行目标对象的目标方法orderService.generate();long end = System.currentTimeMillis();System.out.println("耗时(毫秒):" + (end - begin));}@Overridepublic void modify() {long begin = System.currentTimeMillis();orderService.modify();long end = System.currentTimeMillis();System.out.println("耗时(毫秒):" + (end - begin));}@Overridepublic void detail() {long begin = System.currentTimeMillis();orderService.detail();long end = System.currentTimeMillis();System.out.println("耗时(毫秒):" + (end - begin));}
}

这种方式的优点:

符合OCP开闭原则,同时采用的是关联关系,所以程序的耦合度较低。所以这种方案是被推荐的 

package org.qiu.proxy.client;import org.qiu.proxy.service.OrderService;
import org.qiu.proxy.service.OrderServiceImpl;
import org.qiu.proxy.service.OrderServiceImplSub;
import org.qiu.proxy.service.OrderServiceProxy;/*** @author 秋玄* @version 1.0* @email qiu_2022@aliyun.com* @project Spring* @package org.qiu.proxy.client* @date 2022-11-16-13:13* @since 1.0*/
public class Test {public static void main(String[] args) {// 创建目标对象OrderService target = new OrderServiceImpl();// 创建代理对象OrderService proxy = new OrderServiceProxy(target);// 调用代理对象的代理方法proxy.generate();proxy.modify();proxy.detail();}
}

运行效果:  

以上就是代理模式中的静态代理,其中:

OrderService 接口是代理类和目标类的共同接口

OrderServiceImpl 是目标类

OrderServiceProxy 是代理类

思考一下:如果系统中业务接口很多,一个接口对应一个代理类,显然也是不合理的,会导致类爆炸。怎么解决这个问题?动态代理可以解决。因为在动态代理中可以在内存中动态的为我们生成代理类的字节码。代理类不需要我们写了。类爆炸解决了,而且代码只需要写一次,代码也会得到复用

 

三、动态代理 

在程序运行阶段,在内存中动态生成代理类,被称为动态代理,目的是为了减少代理类的数量,解决代码复用的问题

在内存当中动态生成类的技术常见的包括:

  • JDK 动态代理技术:只能代理接口

  • CGLIB 动态代理技术:CGLIB(Code Generation Library)是一个开源项目。是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展 Java 类与实现 Java 接口。它既可以代理接口,又可以代理类,底层是通过继承的方式实现的。性能比 JDK 动态代理要好(底层有一个小而快的字节码处理框架ASM)

  • Javassist 动态代理技术:Javassist 是一个开源的分析、编辑和创建 Java 字节码的类库。是由东京工业大学的数学和计算机科学系的 Shigeru Chiba (千叶 滋)所创建的。它已加入了开放源代码 JBoss 应用服务器项目,通过使用 Javassist 对字节码操作为 JBoss 实现动态"AOP"框架。

JDK 动态代理 

package org.qiu.proxy.service;/*** 订单业务接口* @author 秋玄* @version 1.0* @email qiu_2022@aliyun.com* @project Spring* @package org.qiu.proxy.service* @date 2022-11-20-08:23* @since 1.0*/
public interface OrderService {/*** 生成订单*/void generate();/*** 修改订单信息*/void modify();/*** 查看订单详情*/void detail();
}
package org.qiu.proxy.service;/*** @author 秋玄* @version 1.0* @email qiu_2022@aliyun.com* @project Spring* @package org.qiu.proxy.service* @date 2022-11-20-08:23* @since 1.0*/
public class OrderServiceImpl implements OrderService{@Overridepublic void generate() {// 模拟网络延迟try {Thread.sleep(1024);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("订单已生成!");}@Overridepublic void modify() {// 模拟网络延迟try {Thread.sleep(512);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("订单已修改!");}@Overridepublic void detail() {// 模拟网络延迟try {Thread.sleep(800);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("订单详情......");}
}

使用静态代理的时候,除了以上一个接口和一个实现类之外,还需要写一个代理类 UserServiceProxy!在动态代理中UserServiceProxy 代理类是可以动态生成的,这个类不需要写。我们直接写客户端程序即可:  

package org.qiu.proxy.client;import org.qiu.proxy.service.OrderService;
import org.qiu.proxy.service.OrderServiceImpl;
import org.qiu.proxy.service.TimeInvocatioinHandler;
import org.qiu.proxy.util.ProxyUtil;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;/*** @author 秋玄* @version 1.0* @email qiu_2022@aliyun.com* @project Spring* @package org.qiu.proxy.client* @date 2022-11-20-08:22* @since 1.0*/
public class Test {public static void main(String[] args) {OrderService target = new OrderServiceImpl();/*** 参数解析:* 参数一:Classloader loader 类加载器*      JDK要求,目标类的类加载器必须和代理类的类加载器使用同一个* 参数二:Class<?>[] interfaces 代理类要实现的接口*      代理类和目标类要实现同一个接口或同一些接口* 参数三:InvocationHandler h 调用处理器对象(是一个接口)*      在这里实现功能的增强(这里采用内部实现类,也可以将其独立出来)*/OrderService orderServiceProxy = (OrderService) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new TimeInvocatioinHandler(target));orderServiceProxy.detail();orderServiceProxy.modify();orderServiceProxy.generate();}
}
package org.qiu.proxy.service;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;/*** @author 秋玄* @version 1.0* @email qiu_2022@aliyun.com* @project Spring* @package org.qiu.proxy.service* @date 2022-11-20-09:01* @since 1.0*/
public class TimeInvocatioinHandler implements InvocationHandler {private Object target;public TimeInvocatioinHandler(Object target) {this.target = target;}/*** invoke 什么时候被调用?*  当代理对象调用代理方法的时候,注册在 InvocationHandler 调用处理器当中的 invoke 方法被调用** @param proxy     代理对象的引用* @param method    目标对象上的目标方法* @param args      目标方法上的实际参数* @return          若代理对象代用代理方法之后需要返回结果的话,invoke方法必须将目标对象目标方法执行结果继续返回*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {long begin = System.currentTimeMillis();// 调用目标对象上的目标方法Object resultValue = method.invoke(target, args);long end = System.currentTimeMillis();System.out.println("耗时(毫秒):" + (end - begin));return null;}
}

上面调用 JDK 自带的方法比较繁琐,这里可以封装一个工具类,方便使用:  

package org.qiu.proxy.util;import org.qiu.proxy.service.OrderService;
import org.qiu.proxy.service.TimeInvocatioinHandler;import java.lang.reflect.Proxy;/*** @author 秋玄* @version 1.0* @email qiu_2022@aliyun.com* @project Spring* @package org.qiu.proxy.util* @date 2022-11-20-09:12* @since 1.0*/
public class ProxyUtil {/*** 获取代理对象(JDK动态代理)* @param target* @return*/public static Object newProxyInstance(Object target){return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new TimeInvocatioinHandler(target));}}
package org.qiu.proxy.client;import org.qiu.proxy.service.OrderService;
import org.qiu.proxy.service.OrderServiceImpl;
import org.qiu.proxy.service.TimeInvocatioinHandler;
import org.qiu.proxy.util.ProxyUtil;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;/*** @author 秋玄* @version 1.0* @email qiu_2022@aliyun.com* @project Spring* @package org.qiu.proxy.client* @date 2022-11-20-08:22* @since 1.0*/
public class Test {public static void main(String[] args) {OrderService target = new OrderServiceImpl();/*** 参数解析:* 参数一:Classloader loader 类加载器*      JDK要求,目标类的类加载器必须和代理类的类加载器使用同一个* 参数二:Class<?>[] interfaces 代理类要实现的接口*      代理类和目标类要实现同一个接口或同一些接口* 参数三:InvocationHandler h 调用处理器对象(是一个接口)*      在这里实现功能的增强(这里采用内部实现类,也可以将其独立出来)*//*OrderService orderServiceProxy = (OrderService) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new TimeInvocatioinHandler(target));*/// 工具类封装OrderService orderServiceProxy = (OrderService) ProxyUtil.newProxyInstance(target);orderServiceProxy.detail();orderServiceProxy.modify();orderServiceProxy.generate();}
}

 

CGLIB 动态代理

CGLIB 既可以代理接口,又可以代理类。底层采用继承的方式实现。所以被代理的目标类不能使用 final 修饰。

使用CGLIB,需要引入它的依赖:

<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.3.0</version>
</dependency>

准备一个没有实现接口的类,如下:  

package org.qiu.proxy.service;/*** @author 秋玄* @version 1.0* @email qiu_2022@aliyun.com* @project Spring* @package org.qiu.proxy.service* @date 2022-11-20-09:22* @since 1.0*/
public class UserService {public void login(){System.out.println("用户正在登录系统....");}public void logout(){System.out.println("用户正在退出系统....");}
}

使用 CGLIB 在内存中为 UserService 类生成代理类,并创建对象:  

package org.qiu.proxy.client;import net.sf.cglib.proxy.Enhancer;
import org.qiu.proxy.service.TimerMethodInterceptor;
import org.qiu.proxy.service.UserService;/*** @author 秋玄* @version 1.0* @email qiu_2022@aliyun.com* @project Spring* @package org.qiu.proxy.client* @date 2022-11-20-09:23* @since 1.0*/
public class Client {public static void main(String[] args) {// 创建字节码增强器Enhancer enhancer = new Enhancer();// 告诉cglib要继承哪个类enhancer.setSuperclass(UserService.class);// 设置回调接口enhancer.setCallback(方法拦截器对象);// 生成源码,编译class,加载到JVM,并创建代理对象UserService userServiceProxy = (UserService)enhancer.create();userServiceProxy.login();userServiceProxy.logout();}
}

和JDK动态代理原理差不多,在CGLIB中需要提供的不是InvocationHandler,而是:net.sf.cglib.proxy.MethodInterceptor

编写MethodInterceptor接口实现类:

package org.qiu.proxy.service;import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;/*** @author 秋玄* @version 1.0* @email qiu_2022@aliyun.com* @project Spring* @package org.qiu.proxy.service* @date 2022-11-20-09:24* @since 1.0*/
public class TimerMethodInterceptor implements MethodInterceptor {@Overridepublic Object intercept(Object target, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {return null;}
}

 

MethodInterceptor接口中有一个方法intercept(),该方法有4个参数:

第一个参数:目标对象

第二个参数:目标方法

第三个参数:目标方法调用时的实参

第四个参数:代理方法

在MethodInterceptor的intercept()方法中调用目标以及添加增强:

package org.qiu.proxy.service;import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;/*** @author 秋玄* @version 1.0* @email qiu_2022@aliyun.com* @project Spring* @package org.qiu.proxy.service* @date 2022-11-20-09:24* @since 1.0*/
public class TimerMethodInterceptor implements MethodInterceptor {@Overridepublic Object intercept(Object target, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {// 前增强long begin = System.currentTimeMillis();// 调用目标Object retValue = methodProxy.invokeSuper(target, objects);// 后增强long end = System.currentTimeMillis();System.out.println("耗时" + (end - begin) + "毫秒");// 一定要返回return retValue;}
}

回调已经写完了,可以修改客户端程序了:  

package org.qiu.proxy.client;import net.sf.cglib.proxy.Enhancer;
import org.qiu.proxy.service.TimerMethodInterceptor;
import org.qiu.proxy.service.UserService;/*** @author 秋玄* @version 1.0* @email qiu_2022@aliyun.com* @project Spring* @package org.qiu.proxy.client* @date 2022-11-20-09:23* @since 1.0*/
public class Client {public static void main(String[] args) {// 创建字节码增强器Enhancer enhancer = new Enhancer();// 告诉cglib要继承哪个类enhancer.setSuperclass(UserService.class);// 设置回调接口enhancer.setCallback(new TimerMethodInterceptor());// 生成源码,编译class,加载到JVM,并创建代理对象UserService userServiceProxy = (UserService)enhancer.create();userServiceProxy.login();userServiceProxy.logout();}
}

对于高版本的JDK,如果使用CGLIB,需要在启动项中添加两个启动参数:  

  • --add-opens java.base/java.lang=ALL-UNNAMED

  • --add-opens java.base/sun.net.util=ALL-UNNAMED

 

一  叶  知  秋,奥  妙  玄  心

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

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

相关文章

IDEA终端环境配置

Idea如何配置终端&#xff1b; 第一步&#xff1a;找到我的电脑&#xff0c;右击——属性——高级系统设置——环境变量 先配置path: 在后面加入&#xff1a;C:\Program Files (x86)\Java\jdk1.7.0_75\bin&#xff08;每个人放置jdk的位置不同。&#xff09; 新建classpath:…

华为OD机试【贪吃的猴子】(java)(200分)

1、题目描述 只贪吃的猴子&#xff0c;来到一个果园&#xff0c;发现许多串香蕉排成一行&#xff0c;每串香蕉上有若干根香蕉。每串香蕉的根数由数组numbers给出。 猴子获取香蕉&#xff0c;每次都只能从行的开头或者末尾获取&#xff0c;并且只能获取N次&#xff0c;求猴子最…

机器人系统ros2-开发实践08-了解如何使用 tf2 来访问坐标帧转换(Python)

tf2 库允许你在 ROS 节点中查询两个帧之间的转换。这个查询可以是阻塞的&#xff0c;也可以是非阻塞的&#xff0c;取决于你的需求。下面是一个基本的 Python 示例&#xff0c;展示如何在 ROS 节点中使用 tf2 查询帧转换。 本教程假设您已完成tf2 静态广播器教程 (Python)和tf…

如何高效解决渠道问题

品牌渠道会围绕销售做一系列活动&#xff0c;定价也会影响渠道的发展&#xff0c;同样的维护好价格&#xff0c;对渠道来说同样重要&#xff0c;渠道中常见的问题包含低价、窜货等&#xff0c;当低价问题不及时解决&#xff0c;会波及影响更多链接&#xff0c;使其他店铺为了流…

力扣刷题第1天:消失的数字

大家好啊&#xff0c;从今天开始将会和大家一起刷题&#xff0c;从今天开始小生也会开辟新的专栏。&#x1f61c;&#x1f61c;&#x1f61c; 目录 第一部分&#xff1a;题目描述 第二部分&#xff1a;题目分析 第三部分&#xff1a;解决方法 3.1 思路一&#xff1a;先排序…

企业短信平台群发_专业群发短信平台

企业平台群发是一种方便、高效的营销方式&#xff0c;通过专业群发平台&#xff0c;企业能够快速、准确地向大量目标客户发送&#xff0c;提高品牌知名度、促进销售和客户互动。下面将详细介绍企业短信平台群发的优势及使用方法。 优势 提高信息覆盖率 企业平台群发可以让企业…

html--瀑布效果

<!doctype html> <html> <head> <meta charset"utf-8"> <title>瀑布效果</title><style> body {background: #222;color: white;overflow:hidden; }#container {box-shadow: inset 0 1px 0 #444, 0 -1px 0 #000;height: 1…

Vue 插槽

Vue插槽是一种特殊的语法&#xff0c;用于在组件中定义可复用的模板部分。它允许开发者在组件的标记中声明一个或多个插槽&#xff0c;然后在使用该组件时&#xff0c;可以根据自己的需求将内容插入到这些插槽中。 Vue插槽分为默认插槽和具名插槽两种。 目录 默认插槽 语法…

【图书推荐】《JSP+Servlet+Tomcat应用开发从零开始学(第3版)》

本书目的 系统讲解JSPServletTomcat开发技术&#xff0c;帮助读者用最短的时间掌握Java Web应用开发技能。 内容简介 本书全面系统地介绍JSPServletTomcat开发中涉及的相关技术要点和实战技巧。本书内容讲解循序渐进&#xff0c;结合丰富的示例使零基础的读者能够熟练掌握JSP…

Leetcode—2105. 给植物浇水 II【中等】

2024每日刷题&#xff08;131&#xff09; Leetcode—2105. 给植物浇水 II 实现代码 class Solution { public:int minimumRefill(vector<int>& plants, int capacityA, int capacityB) {int size plants.size();int i 0;int j size - 1;int capA capacityA;in…

探秘Tailwind CSS:前端开发的加速器(Tailwind CSS让CSS编写更简洁)

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 Tailwind CSS 📒📝 快速体验📝 深入学习⚓️ 相关链接 ⚓️📖 介绍 📖 在这个快速迭代的互联网时代,前端开发效率和设计质量的双重要求,使得开发者们不断寻求更高效的工具和方法。今天,我们要介绍的是一个能够极大…

酷柚易汛ERP源码部署/售后更新/搭建/上线维护

一款基于FastAdminThinkPHPLayui开发的ERP管理系统&#xff0c;帮助中小企业实现ERP管理规范化&#xff0c;此系统能为你解决五大方面的经营问题&#xff1a;1.采购管理 2.销售管理 3.仓库管理 4.资金管理 5.生产管理&#xff0c;适用于&#xff1a;服装鞋帽、化妆品、机械机电…

设计模式之服务定位器模式

想象一下&#xff0c;你的Java应用是一座庞大的迷宫&#xff0c;里面藏着无数宝贵的服务宝藏&#xff0c;而你正需要一张精确的藏宝图来指引方向&#xff0c;迅速找到并利用这些宝藏。服务定位器模式&#xff0c;正是这样一张神奇的地图&#xff0c;它帮你动态定位并获取应用中…

『先进技术助力』Kompas AI:智能AI代理在工作中的应用与效率提升

『智能化未来』Kompas AI如何改变我们的工作方式&#xff1f; 在这个信息时代&#xff0c;利用AI聊天机器人来处理机械性的工作已经成为一种趋势。ChatGPT作为一种智能助手&#xff0c;不仅能够提高工作效率&#xff0c;还可以帮助我们更明智地做出决策&#xff0c;从而释放出更…

内网安全综合管理系统是什么 | 好用的内网安全管理系统有哪些

内网安全综合管理系统是指一种集成终端管理、网络管理、内容管理、资产管理等功能的综合性安全管理系统。它主要对内网上的主机进行统一安全管理&#xff0c;包括对网络主机用户操作实施监督控制&#xff0c;并对主机中的安全软件&#xff08;如主机入侵监测系统、主机防火墙和…

C++:内存管理

C:内存管理 一、C/C内存分布二、C语言中动态内存管理方式&#xff1a;malloc/calloc/realloc/free三、C内存管理方式1.new/delete操作内置类型2.new和delete操作自定义类型 四、operator new与operator delete函数&#xff08;重点&#xff09;五、new和delete的实现原理1.内置…

【算法】滑动窗口——水果成篮

本篇博客是我对“水果成篮”这道题由暴力解法到滑动窗口思路的具体思路&#xff0c;有需要借鉴即可。 目录 1.题目2.暴力求解3.暴力优化3.1每次right不用回退3.2有些left长度一定不如前一个&#xff0c;不用走&#xff0c;left不回退 4.滑动窗口算法5.总结 1.题目 题目链接&am…

工程技术综合SCI期刊,中科院2区,IF=3+,对国人非常友好!

一、期刊名称 Engineering Analysis with Boundary Elements 二、期刊简介概况 期刊类型&#xff1a;SCI 学科领域&#xff1a;工程技术 影响因子&#xff1a;3.3 中科院分区&#xff1a;2区 出版方式&#xff1a;订阅模式/开放出版 版面费&#xff1a;选择开放出版需支…

MySQL——利用变量进行查询操作

新建链接&#xff0c;自带world数据库&#xff0c;里面自带city表格。 DQL # MySQL利用变量进行查询操作 set cityNameHaarlemmermeer; select * from city where NamecityName;# 多个结果查询 set cityName1Haarlemmermeer; set cityName2Breda; set cityName3Willemstad; s…

何为基差?股指期货的升水和贴水又怎么理解?

基差是一个金融术语&#xff0c;它指的是现货价格和期货价格之间的差额。在股指期货市场中&#xff0c;现货就是指实际的股票指数&#xff0c;而期货则是基于这个指数未来某个时间点的价格预期。基差可以是正的或负的&#xff0c;具体取决于期货价格是高于还是低于现货价格。 1…