Spring(22) Spring中的9种设计模式

目录

    • 一、简单工厂模式(Simple Factory)
    • 二、工厂方法模式(Factory Method)
    • 三、单例模式(Singleton)
    • 四、适配器模式(Adapter)
    • 五、代理模式(Proxy)
    • 七、观察者模式(Observer)
    • 八、策略模式(Strategy)
    • 九、模板方法模式(Template Method)

在软件开发领域,设计模式 是解决常见问题的最佳实践。Spring 框架作为 Java 生态中的佼佼者,其成功在很大程度上 归功于对设计模式的巧妙运用。“Spring 中用到了哪些设计模式?”,这个问题,在 面试 中也比较常见,在此进行整理。

一、简单工厂模式(Simple Factory)

定义:

简单工厂模式:并不属于 GoF(四人组)总结的 23 种设计模式,但它却在实际开发中被频繁使用。其核心是 由一个工厂类根据传入的参数,动态决定创建哪一个产品类的实例。

举例:

Spring 中的 BeanFactory 就是简单工厂模式的体现,根据传入一个唯一的标识来获得 Bean 对象。但是,在传入参数后创建 Bean 还是传入参数前创建 Bean,这个要根据具体情况而定。

Bean 容器的启动阶段:

  • 读取 Bean 的 xml 配置文件,将 Bean 元素分别转换成一个 BeanDefinition 对象。
  • 然后通过 BeanDefinitionRegistry 将这些 Bean 注册到 BeanFactory 中,保存在 ConcurrentHashMap 中。
  • 将 BeanDefinition 注册到了 beanFactory 之后,在这里 Spring 为我们提供了一个扩展的切口,允许我们通过实现接口 BeanFactoryPostProcessor 在此处来插入我们定义的代码。典型的例子就是:PropertyPlaceholderConfigurer,我们一版再配置数据库的 dataSource 时使用到的占位符的值,就是它注入进去的。

设计意义:

  • 松耦合: 可以将原来硬编码的依赖,通过 Spring 的 BeanFactory 这个工厂来注入依赖,也就是说原来只有依赖方和被依赖方,现在我们引入了第三方——spring 的 BeanFactory,由它来解决 Bean 之间的以来问题,达到了松耦合的效果。
  • bean 增强: 通过 Spring 接口的暴露,在实例化 Bean 的阶段我们可以进行一些额外的处理,这些额外的处理只需要让 Bean 实现对应的接口即可,那么 Spring 就会在 Bean 的生命周期调用我们实现的接口来处理该 Bean。

二、工厂方法模式(Factory Method)

定义:

工厂方法模式:定义了一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到子类。

举例:

Spring 使用工厂模式可以通过 BeanFactoryApplicationContext 创建 Bean 对象。两者对比如下:

  • BeanFactory:延迟注入(使用到某个 Bean 的时候才会注入),相比于 ApplicationContext 来说会占用更少的内存,程序启动速度更快。
  • ApplicationContext:容器启动的时候,不管你用没用到,一次性创建所有 Bean。BeanFactory 仅提供了最基本的依赖注入支持,ApplicationContext 扩展了 BeanFactory,除了有 BeanFactory 的功能还有额外更多功能,所以一般开发人员使用 AplicationContext 更多。

ApplicationContext 的三个实现类:

  1. ClassPathXmlApplication:把上下文文件当成类路径资源。
  2. FileSystemXmlApplication:从文件系统中的 XML 文件载入上下文定义信息。
  3. XmlWebApplicationContext:从 Web 系统中的 XML 文件载入上下文定义信息。

实现类使用示例:

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

public Class App  {
    public static void main(String[] args) {
        ApplicationContext contexty = new FileSystemXmlApplicationContext(
        	"D:/IdeaProjects/springboot-demo/src/main/resources/bean-factory-config.xml");

        HelloApplicationContext obj = (HelloApplicationContext) context.getBean("helloApplicationContext");
        obj.getMsg();
    }
}

三、单例模式(Singleton)

定义:

单例模式:确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。

举例:

在我们系统中,有一些对象其实我们只需要一个,比如说:线程池、缓存、对话框、注册表、日志对象、充当打印机、显卡等设备驱动程序的对象。事实上,这一类对象只能有一个实例,如果制造出多个实例就可能会导致一些问题的产生,比如;程序的行为异常、资源使用过量、或者不一致性的结果。

使用单例模式的好处:

  • 对于频繁使用的对象,可以省略创建对象所花费的时间,这对于那些重量级对象而言,是非常可观的一笔系统开销。
  • 由于 new 操作的次数减少,因而对系统内存的使用频率也会降低,这将减轻 GC 压力,缩短 GC 停顿时间。

Spring 中 Bean 的作用域就是 singleton(单例)的。 除了 singleton 作用域,Spring 中 Bean 还有下面几种作用域:

  • prototype:每次获取都会创建一个新的 Bean 实例。也就是说,连续 getBean() 两次,得到的是不同的 Bean 实例。
  • request(仅 Web 应用可用):每一次 HTTP 请求都会产生一个新的 Bean(请求 Bean),该 Bean 仅在前面 HTTP request 内有效。
  • session(仅 Web 应用可用):每一次来自新 session 的 HTTP 请求都会创建一个新的 Bean(会话 Bean),该 Bean 仅在当前 HTTP session 内有效。
  • application/global-session(仅 Web 应用可用):每个 Web 应用在启动时创建一个 Bean(应用 Bean),该 Bean 仅在当前应用启动时间内有效。
  • websocket(仅 Web 应用可用):每一次 WebSocket 会话产生一个新的 Bean。

Spring 通过 ConcurrentHashMap 实现单例注册表的特殊方式实现单例模式。

Spring 实现单例的核心代码如下:

DefaultSingletonBeanRegistry.java (spring-beans-5.2.12.RELEASE.jar)

// 通过 ConcurrentHashMap(线程安全)实现单例注册表
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

// 从单例注册表中获取对象
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    Assert.notNull(beanName, "Bean name must not be null");
    synchronized (this.singletonObjects) {
        // 检查缓存中是否存在实例
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null) {
            // 省略了很多代码...
            try {
                singletonObject = singletonFactory.getObject();
                newSingleton = true;
            }
            // 省略了很多代码...
            // 如果实例对象是新创建的,我们注册到单例注册表中。
            if (newSingleton) {
                addSingleton(beanName, singletonObject);
            }
        }
        return singletonObject;
    }
}

// 将对象添加到单例注册表
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
    Assert.notNull(singletonFactory, "Singleton factory must not be null");
    synchronized (this.singletonObjects) {
        if (!this.singletonObjects.containsKey(beanName)) {
            this.singletonFactories.put(beanName, singletonFactory);
            this.earlySingletonObjects.remove(beanName);
            this.registeredSingletons.add(beanName);
        }
    }
}

单例 Bean 存在线程安全问题吗?

大部分时候我们并没有在项目中使用多线程,所以很少有人会关注这个问题。单例 Bean 存在线程问题,主要是因为当多个线程操作同一个对象的时候是存在资源竞争的

常见的两种解决办法:

  1. 在 Bean 中尽量避免定义可变的成员变量。
  2. 在类中定义一个 ThreadLocal 成员变量,将需要的可变成员变量保存在 ThreadLocal 中(推荐的一种方式)。

不过,大部分 Bean 实际都是无状态的(没有实例变量,比如:Dao、Service),这种情况下,Bean 是线程安全的。


四、适配器模式(Adapter)

定义:

适配器模式:将一个接口转换成客户希望的另一个接口,适配器使接口不兼容的那些类可以一起工作。

举例:

Spring AOP 中的适配器模式:

我们知道 Spring AOP 的实现是基于代理模式,但是 Spring AOP 的增强或通知(Advice)使用到了适配器模式,与之相关的接口是 AdvicorAdapter

Advice 常用的类型有:BeforeAdvice(目标方法调用前,前置通知)、AfterAdvice(目标方法调用后,后置通知)、AfterReturningAdvice(目标方法执行结束后,return 之前)等等。每个类型 Advice(通知)都有对应的拦截器:MethodBeforeAdviceInterceptorAfterReturningAdviceInterceptorThrowsAdviceInterceptor 等等。

Spring 预定义的通知要通过对应的适配器,适配成 MethodInterceptor 接口(方法拦截器)类型的对象(如:MethodBeforeAdviceAdapter 通过调用 getInterceptor 方法,将 MethodBefforeAdvice 适配成 MethodBeforeAdviceInterceptor)。

Spring MVC 中的适配器模式:

在 Spring MVC 中,DispatcherServlet 根据请求信息调用 HandlerMapping,解析请求对应的 Handler。解析到对应的 Handler(也就是我们平常说的 Controller 控制器)后,开始由 HandlerAdapter 适配器处理。HandlerAdapter 作为期望接口,具体的适配器实现类用于对目标类进行适配,Controller 作为需要适配的类。

为什么要在 Spring MVC 中使用适配器模式?

Spring MVC 中的 Controller 种类众多,不同类型的 Controller 通过不同的方式来对请求进行处理。如果不利用适配器模式的话,DispatcherServlet 直接获取对应类型的 Controller,需要的自行来判断,像下面这段代码一样:

if (mappedHandler.getHandler() instanceof MultiActionController) {
    ((MultiActionController) mappedHandler.getHandler()).xxx
} else if (mappedHandler.getHandler() instanceof XXX) {
    ...
} else if (...) {
    ...
}

加入我们再增加一个 Controller 类型就要在上面代码中再加入一行判断语句,这种形式就使得程序难以维护,也违反了设计模式中的开闭原则(对扩展开放,对修改关闭)。


五、代理模式(Proxy)

定义:

代理模式:为其他对象提供一个代理以控制对这个对象的访问。

举例:

代理模式在 AOP 中的应用:

AOP(Aspect-Oriented Programming,面向切面编程):能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如:事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可扩展性和可维护性。

Spring AOP 就是基于动态代理的,如果要代理的对象,实现了某个接口,那么 Spring AOP 会使用 JDK Proxy 去创建代理对象,而对于没有实现接口的对象,就无法使用 JDK Proxy 去进行代理了,这时候 Spring AOP 会使用 Cglib 生成一个被代理对象的子类来作为代理,如下图所示:

在这里插入图片描述

当然,你也可以使用 AspectJ。Spring AOP 已经集成了 AspectJ,AspectJ 应该算得上是 Java 生态系统中最完整的 AOP 框架了。

使用 AOP 之后,我们可以吧一些通用功能抽象出来,在需要用到的地方直接使用即可,这样大大简化了代码量。我们需要增加新功能时也方便,这样也提高了系统扩展性。日志功能、事务管理等等场景都用到了 AOP。

Spring AOP 和 AspectJ AOP 有什么区别?

Spring AOP 属于运行时增强,而 AspectJ 是编译时增强。 Spring AOP 基于代理(Proxying),而 AspectJ 基于字节码操作(Bytecode Manipulation)。

Spring AOP 已经集成了 AspectJ,AspectJ 应该算得上是 Java 生态系统中最完整的 AOP 框架了。AspectJ 相比于 Spring AOP 功能更加强大,但是 Spring AOP 相对来说更简单。如果我们的切面比较少,那么两者性能差异不大。但是,如果切面太多的话,最好选择 AspectJ,它比 Spring AOP 快很多


七、观察者模式(Observer)

定义:

观察者模式:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都得到通知并被自动更新。

举例:

Spring 事件驱动模型就是观察者模式很经典的一个应用。Spring 事件驱动模型非常有用,在很多场景都可以解耦我们的代码。比如我们每次添加商品的时候都需要重新更新商品索引,这个时候就可以利用观察者模式来解决这个问题。

Spring 事件驱动模型中的三种角色:

  • 事件角色: ApplicationEventorg.springframework.context 包下)充当事件的角色,这是一个抽象类,它继承了 java.util.EventObject 并实现了 java.io.Serializable 接口。

Spring 中默认存在以下事件,他们都是对 ApplicationContextEvent 的实现(继承自 ApplicationContextEvent):

  • ContextStartedEvent:ApplicationContext 启动后触发的事件。
  • ContextStoppedEvent:ApplicationContext 停止后触发的事件。
  • ContextRefreshedEvent:ApplicationContext 初始化或刷新完成后触发的事件。
  • ContextClosedEvent:ApplicationContext 关闭后触发的事件。

在这里插入图片描述

  • 事件监听者角色: ApplicationListener 充当了事件监听者角色,它是一个接口,里面只定义了一个 onApplicationEvent() 方法来处理 ApplicationEvent。ApplicationListener 接口类源码如下,从接口定义可以看出接口中的事件只要实现了 ApplicationEvent 就可以了。所以,在 Spring 中我们只要实现 ApplicationListener 接口的 onApplicationEvent() 方法即可完成监听事件。
package org.springframework.context;

import java.util.EventListener;

@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
    void onApplicationEvent(E var1);
}
  • 事件发布者角色: ApplicationEventPublisher 充当了事件的发布者,它也是一个接口。
@FunctionalInterface
public interface ApplicationEventPublisher {
    default void publishEvent(ApplicationEvent event) {
        this.publishEvent((Object)event);
    }
    
    void publishEvent(Object var1);
}

ApplicationEventPublisher 接口的 publishEvent() 这个方法在 AbstractApplicationContext 类中被实现,阅读这个方法的实现,你会发现实际上事件真正是通过 ApplicationEventMulticaster 来广播出去的。具体内容过多,就不在这里分析了。

Spring 的事件流程总结:

  1. 定义一个事件:实现一个继承自 ApplicationEvent,并且写相应的构造函数;
  2. 定义一个事件监听者:实现 ApplicationListener 接口,重写 onApplicationEvent() 方法;
  3. 使用事件发布者发布消息:可以通过 ApplicationEventPublisherpublishEvent() 方法发布消息。

DemoEvent.java

// 定义一个事件,继承自 ApplicationEvent 并且写相应的构造函数
public class DemoEvent extends ApplicationEvent {
    private static final long serialVersionUID = 1L;
    
    private String message;
    
    public DemoEvent(Object source, String message) {
        super(source);
        this.message = message;
    }
    
    public String getMessage() {
        return message;
    }
}

DemoListener.java

// 定义一个事件监听者,实现 ApplicationListener 接口,重写 onApplicationEvent() 方法
@Component
public class DemoListener implements ApplicationListener<DemoEvent> {
    
    // 使用onApplicationEvent接收消息
    @Override
    public void onApplicationEvent(DemoEvent event) {
        String msg = event.getMessage();
        System.out.println("接收到的消息是:" + msg);
    }
}

DemoPublisher.java

@Component
public class DemoPublisher {
    
    @Autowired
    private ApplicationContext applicationContext;
    
    public void publish(String message) {
        // 发布事件
        applicationContext.publishEvent(new DemoEvent(this, message));
    }
}

当调用 DemoPublisherpublish() 方法的时候,比如 demoPublisher.publish("你好")

@RestController
@RequestMapping("/demo")
public class DemoController {

    @Resource
    private DemoPublisher demoPublisher;

    @GetMapping("/publish")
    public Result<Object> publish(@RequestParam String message) {
        demoPublisher.publishEvent(message);
        return Result.succeed();
    }
}

请求地址:http://localhost:8080/demo/publish?message=test

执行结果:

控制台就会打印出:接收到的信息是:你好。

在这里插入图片描述


八、策略模式(Strategy)

定义:

策略模式:定义了一系列的算法,并将每一个算法封装起来,使它们可以互相替换。策略模式让算法独立于使用它的客户。

举例:

Spring 框架的资源访问 Resource 接口。该接口提供了更强的资源访问能力,Spring 框架本身大量使用了 Resource 接口来访问底层资源。

Resource 接口介绍:

Resource 接口是具体资源访问策略的抽象,也是所有资源访问类所实现的接口。

Resource 接口主要提供了如下几个方法:

  • getInputStream(): 定位打开资源,返回资源对应的输入流。每次调用都返回新的输入流。调用者必须负责关闭输入流。
  • exists(): 返回 Resource 所指向的资源是否存在。
  • isOpen(): 返回资源文件是否打开,如果资源文件不能多次读取,每次读取结束应该显示关闭,以防止资源泄露。
  • getDescription(): 返回资源的描述信息,通常用于资源处理出错时输出该信息,通常是全限定文件名或实际 URL。
  • getFile(): 返回资源对应的 File 对象。
  • getURL(): 返回资源对应的 URL 对象。

最后两个方法通常无须使用,仅在通过简单方法访问无法实现时,Resource 提供传统的资源访问的功能。

Resource 接口本身没有提供访问任何底层资源的实现逻辑,针对不同的底层资源,Spring 将会提供不同的 Resource 实现类,不同的实现类负责不同的资源访问逻辑。

Spring 为 Resource 接口提供了如下实现类:

  • UrlResource: 访问网络资源的实现类。
  • ClassPathResource: 访问类加载路径里资源的实现类。
  • FileSystemResource: 访问文件系统里资源的实现类。
  • ServletContextResource: 访问相对于 ServletContext 路径里的资源的实现类。
  • InputStreamResource: 访问输入流资源的实现类。
  • ByteArrayResource: 访问字节数组资源的实现类。

这些 Resource 实现类,针对不同的底层资源,提供了相应的资源访问逻辑,并提供便携的包装,以利于客户端程序的资源访问。


九、模板方法模式(Template Method)

定义:

模板方法模式:在一个方法中定义了一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法的某些步骤。

举例:

Spring 中 JdbcTemplateHibernateTemplate 等以 Template 结尾的对接入内容进行操作的类,它们就使用到了模板方法。一般情况下,我们都是使用继承的方法来实现模板模式,但是 Spring 并没有使用这种方式,而是使用 Callback 模板与模板方法模式配合,既达到了代码复用的效果,同时增加了灵活性。

下面是一个模板模式的使用示例:

public abstract class Template {
    public void operate1() {
        // 当前类实现
        operate2();
        operate3();
    }

    // 被子类实现的方法
    public abstract void operate2();
    public abstract void operate3();
}

public class TemplateImpl extends Template {
    
    @Override
    public void operate2() {
        // 当前类实现
    }

    @Override
    public void operate3() {
        // 当前类实现
    }
}

整理完毕,完结撒花~ 🌻





参考地址:

1.Spring 中经典的 9 种设计模式,打死也要记住啊!https://zhuanlan.zhihu.com/p/114244039

2.Spring 中的设计模式详解,https://javaguide.cn/system-design/framework/spring/spring-design-patterns-summary.html

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

洛谷p1225 c++(使用高精度)

题解: 一开始我这个代码想到的是使用递归来求解 int digui(int n){int sum=0;if(n==1)sum=1;if(n==2)sum=2;if(n==1||n==2)return sum;if(n>2){return sum+=digui(n-1)+digui(n-2);} } 但是后面发现明显超时,我试图用记忆化搜索来抢救一下,所以就有了下面代码 int di…

前端食堂技术周刊第 114 期:Interop 2024、TS 5.4 RC、2 月登陆浏览器的新功能、JSR、AI SDK 3.0

美味值&#xff1a;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f; 口味&#xff1a;凉拌鸡架 食堂技术周刊仓库地址&#xff1a;https://github.com/Geekhyt/weekly 大家好&#xff0c;我是童欧巴。欢迎来到前端食堂技术周刊&#xff0c;我们先来看下…

Github 2024-03-05 Python开源项目日报 Top10

根据Github Trendings的统计&#xff0c;今日(2024-03-05统计)共有10个项目上榜。根据开发语言中项目的数量&#xff0c;汇总情况如下&#xff1a; 开发语言项目数量Python项目10TypeScript项目1 稳定扩散Web UI 创建周期&#xff1a;512 天开发语言&#xff1a;Python协议类…

数仓实战——京东数据指标体系的构建与实践

目录 一、如何理解指标体系 1.1 指标和指标体系的基本含义 1.2 指标和和标签的区别 1.3 指标体系在数据链路中的位置和作用 1.4 流量指标体系 1.5 指标体系如何向上支撑业务应用 1.6 指标体系背后的数据加工逻辑 二、如何搭建和应用指标体系 2.1 指标体系建设方法—OS…

eclipse搭建java web项目

准备条件 eclipsejdk1.8 &#xff08;配置jdk环境&#xff09;apache-tomcat-8.5.97&#xff08;记住安装位置&#xff09; 一 点击完成 开始创建javaweb项目 import java.io.IOException; import java.io.PrintWriter;import javax.servlet.ServletException; import javax.s…

IP传输方式——组播

组播作为IP传输三种方式之一&#xff0c;指的是报文从一个源发出&#xff0c;被转发到一组特定的接收者&#xff0c;相同的报文在每条链路上最多有一份。相较于传统的单播和广播&#xff0c;组播可以有效地节约网络带宽、降低网络负载&#xff0c;所以被广泛应用于IPTV、实时数…

深度学习-Pytorch实现经典VGGNet网络

深度学习-Pytorch实现经典VGGNet网络 深度学习中&#xff0c;经典网络引领一波又一波的技术革命&#xff0c;从LetNet到当前最火的GPT所用的Transformer&#xff0c;它们把AI技术不断推向高潮。2012年AlexNet大放异彩&#xff0c;它把深度学习技术引领第一个高峰&#xff0c;打…

如何利用Flutter来写后端 服务端应用

前言 Flutter是谷歌推出的一款跨平台开发框架&#xff0c;现在属于此领域star最多的框架&#xff0c;其被广泛应用于构建前台界面&#xff0c;但或许很少人知道&#xff0c;他也可以写后端应用。 本文主角 flutter非常著名的getx库推出的get server jonataslaw/get_server:…

广播、组播域套接字的实现

思维导图&#xff1a; 广播模式&#xff1a; 发送端&#xff1a; #include <myhead.h> int main(int argc, const char *argv[]) {//创建套接字int sfdsocket(AF_INET,SOCK_DGRAM,0);if(sfd-1){perror("socket error");return -1;}//设置套接字允许广播属性i…

VS2022连接数据库以及常用的连接函数

下面是如何配置以及设置VS2022连接数据库 第一步:打开mysql的安装目录&#xff0c;默认安装目录如下&#xff1a;C:\Program Files\MySQL\MySQL Server 8.0&#xff0c;确认 lib 目录和include 目录是否存在。 第二步&#xff1a;打开VS2019&#xff0c;新建一个空工程,控制台…

STM32 | STM32时钟分析、GPIO分析、寄存器地址查找、LED灯开发(第二天)

STM32 第二天 一、 STM32时钟分析 寄存器&#xff1a;寄存器的功能是存储二进制代码&#xff0c;它是由具有存储功能的触发器组合起来构成的。一个触发器可以存储1位二进制代码&#xff0c;故存放n位二进制代码的寄存器&#xff0c;需用n个触发器来构成 在计算机领域&#x…

远程桌面连接不上服务器怎么办?

在进行远程桌面连接时&#xff0c;有时候会遇到连接不上服务器的问题&#xff0c;这给我们的工作和生活带来了很多不便。下面&#xff0c;我们来了解一下解决这个问题的方法和工具。 【天联】组网的介绍 【天联】组网是一款异地组网内网穿透产品&#xff0c;由北京金万维科技有…

快速上手:在 Android 设备上运行 Pipy

Pipy 作为一个高性能、低资源消耗的可编程代理&#xff0c;通过支持多种计算架构和操作系统&#xff0c;Pipy 确保了它的通用性和灵活性&#xff0c;能够适应不同的部署环境&#xff0c;包括但不限于云环境、边缘计算以及物联网场景。它能够在 X86、ARM64、海光、龙芯、RISC-V …

Linux网络编程 ——UDP 通信

Linux网络编程 ——UDP 通信 1. UDP1.1 UDP 通信1.2 广播1.3 组播&#xff08;多播&#xff09; 2. 本地套接字 1. UDP 1.1 UDP 通信 输入 man 2 sendto 查看说明文档 #include <sys/types.h> #include <sys/socket.h>ssize_t sendto(int sockfd, const void *buf…

GlusterFS系统内核调优

转载说明&#xff1a;如果您喜欢这篇文章并打算转载它&#xff0c;请私信作者取得授权。感谢您喜爱本文&#xff0c;请文明转载&#xff0c;谢谢。 相关文章&#xff1a; 分布式存储——GlusterFS 关于GlusterFS的卷 GlusterFS—新手陷阱 GlusterFS常用命令集 前言 本文总…

深度学习预测分析API:金融领域的Game Changer

&#x1f680; 引言 在这个AI遍地开花的时代&#xff0c;谁能成为金融领域的真正Game Changer&#xff1f;那必然是是深度学习预测分析API。如大脑般高效运转的系统不仅颠覆了传统操作&#xff0c;更是以无与伦比的速度和精度赋予了金融数据以全新的生命。 &#x1f4bc; 广泛…

Doris实战——特步集团零售数据仓库项目实践

目录 一、背景 二、总体架构 三、ETL实践 3.1 批量数据的导入 3.2 实时数据接入 3.3 数据加工 3.4 BI 查询 四、实时需求响应 五、其他经验 5.1 Doris BE内存溢出 5.2 SQL任务超时 5.3 删除语句不支持表达式 5.4 Drop 表闪回 六、未来展望 原文大佬的这篇Doris数…

C# Winform画图绘制圆形

一、因为绘制的圆形灯需要根据不同的状态切换颜色,所以就将圆形灯创建为用户控件 二、圆形灯用户控件 1、创建用户控件UCLight 2、设值用户控件大小(30,30)。放一个label标签,AutoSize为false(不自动调整大小),Dock为Fill(填充),textaglign为居中显示。 private Color R…

LLM春招准备(1)

llm排序 GPT4V GPT-4V可以很好地理解直接绘制在图像上的视觉指示。它可以直接识别叠加在图像上的不同类型的视觉标记作为指针&#xff0c;例如圆形、方框和手绘&#xff08;见下图&#xff09;。虽然GPT-4V能够直接理解坐标&#xff0c;但相比于仅文本坐标&#xff0c;GPT-4V在…

【探索AI】二十一 深度学习之第4周:循环神经网络(RNN)与长短时记忆(LSTM)

循环神经网络&#xff08;RNN&#xff09;与长短时记忆&#xff08;LSTM&#xff09; RNN的基本原理与结构LSTM的原理与实现序列建模与文本生成任务实践&#xff1a;使用RNN或LSTM进行文本分类或生成任务步骤 1: 数据准备步骤 2: 构建模型步骤 3: 定义损失函数和优化器步骤 4: …
最新文章