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

设计模式之单例模式~

设计模式包含很多,但与面试相关的设计模式是单例模式,单例模式的写法有好几种,我们主要学习这三种—饿汉式单例,懒汉式单例、登记式单例,这篇文章我们主要学习饿汉式单例

单例模式:

满足要点:

私有构造
提供静态全局变量
提供专门访问静态全局变量的方法

饿汉式实现:

实现类:

import java.io.Serializable;//1:饿汉式
public class Singleton1 implements Serializable {//私有构造private Singleton1(){System.out.println("private Singleton1");}//提供静态的全局变量private  static final Singleton1 INSTANCE= new Singleton1();//相对于懒汉式是提前创建的//提供专有的方法去获得静态变量public static Singleton1 getInstance(){return  INSTANCE;}public static void otherMethod(){System.out.println("otherMethod()");}
}

测试类:

public class Test_Singleton1 {public static void main(String[] args) {//触发当前类的加载链接--导致该类的初始化操作被创建,当我们调用otherMethod()方法时,该类已经被创建,因为在输出的内容中,包含该类私有构造中的内容Singleton1.otherMethod();System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");//下面我们调用getInstance()方法时,得到的对象为上述已经创建好的对象System.out.println(Singleton1.getInstance());System.out.println(Singleton1.getInstance());}
}

输出:

private Singleton1
otherMethod()
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Singleton1@7ef20235
Singleton1@7ef20235

由于上述的单例我们实现的是Serializable接口,因此很容易被破坏,常见的破坏方式有以下几种:

反射破坏单例:

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;public class Test_Singleton1 {Singleton1.otherMethod();System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");System.out.println(Singleton1.getInstance());System.out.println(Singleton1.getInstance());//反射破坏单例reflection(Singleton1.class);}private static void reflection(Class<?> classz) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {//通过getDeclaredConstructor获得私有构造Constructor<?> constructor=classz.getDeclaredConstructor();//通过setAccessible使得私有的构造方法也可以被使用constructor.setAccessible(true);//使用newInstance创建新的对象System.out.println("反射创建实例:"+constructor.newInstance());}
}

输出:

private Singleton1
otherMethod()
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Singleton1@7ef20235
Singleton1@7ef20235
private Singleton1
反射创建实例:Singleton1@15aeb7ab

经过反射操作的Singleton1已经不是单例了,由于getInstance和反射创建的对象并不是同一个,一个类有两个对象,并不符合单例

newInstance()和new()区别:

创建对象的方式不同,newInstance()是实用类的加载机制,new()则是直接创建一个类newInstance创建类是这个类必须已经加载过且已经连接(Class.forName(“A”)这个过程)new创建类是则不需要这个类加载过

newInstance实际上是把new这个方式分解为两步,首先调用class的加载方法加载某个类,然后实例化,这样做的好处体现在我们可以在调用class的静态加载方法forName时获得更好的灵活性

newInstance 是弱类型(GC是回收对象的限制条件很低,容易被回收)、低效率、只能调用无参构造

new是强类型(GC不会自动回收,只有所有的指向对象的引用被移除是才会被回收,若对象生命周期已经结束,但引用没有被移除,经常会出现内存溢出)

预防反射破坏单例:

解决方法:

在私有构造中加入如下代码,当单例对象已经被创建过时,则直接抛出异常

if(INSTANCE!=null) {throw new RuntimeException("单例对象不能重复创建");
}

测试结果如下:

对象只被创建了一次,第二次通过反射创建对象时,直接抛出异常

在这里插入图片描述

反序列化破坏单例:

import java.io.*;
import java.lang.reflect.InvocationTargetException;public class Test_Singleton1 {public static void main(String[] args) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, IOException, ClassNotFoundException {Singleton1.otherMethod();System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");System.out.println(Singleton1.getInstance());System.out.println(Singleton1.getInstance());//反序列化破坏单例serializable(Singleton1.getInstance());}private static void  serializable(Object instance) throws IOException, ClassNotFoundException {ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream();//创建输出流对象ObjectOutputStream objectOutputStream=new ObjectOutputStream(byteArrayOutputStream);//通过writeObject将获取到的对象转变为字节流objectOutputStream.writeObject(instance);//创建文件输入流对象//toByteArray()方法是将一个ByteArrayOutputStream对象转换为byte字符数组返回ObjectInputStream objectInputStream=new ObjectInputStream(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));//通过readObject将转变后的字节流还原成对象System.out.println("反序列化创建实例:"+objectInputStream.readObject());}
}

输出:

这种反序列化的过程不仅可以产生新的对象,且并不实现构造方法

private Singleton1
otherMethod()
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Singleton1@7ef20235
Singleton1@7ef20235
反序列化创建实例:Singleton1@1a93a7ca

预防反序列化破坏单例:

解决办法为在Singleton1类中重写readResolve方法,使得它的返回值为初始创建的instance对象,而不是通过反序列化再创建新的对象

public Object readResolve(){return INSTANCE;}

Unsafe破坏单例:

 unsafe(Singleton1.class);private static void unsafe(Class<?> clazz) throws InstantiationException {Object o = UnsafeUtils.getUnsafe().allocateInstance(clazz);System.out.println("Unsafe 创建实例:" + o);
}

Unsafe是JDK内置的一个类,它并不是Java标准类,一般的开发者不会涉及此类的开发,它不需要调用构造函数,且这种破坏方式目前没有解决的办法

枚举类实现饿汉式单例:

enum_Sington类:

public enum enum_Sington {INSTANCE;private enum_Sington(){System.out.println("private enum_Sington()");}public static enum_Sington getInstance(){return INSTANCE;}@Overridepublic String toString() {return getClass().getName()+"@"+Integer.toHexString(hashCode());}public static void otherMethod(){System.out.println("otherMethod()");}
}

测试类:

import java.io.*;
import java.lang.reflect.InvocationTargetException;
public class Test_Sington2 {//单例模式-饿汉式public static void main(String[] args) throws InvocationTargetException, NoSuchMethodException, InstantiationException,IOException, ClassNotFoundException {enum_Sington.otherMethod();System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");System.out.println(enum_Sington.getInstance());System.out.println(enum_Sington.getInstance());}
}

输出:

private enum_Sington()
otherMethod()
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
enum_Sington@7ef20235
enum_Sington@7ef20235

然而对于枚举类,反序列化并不能将其破坏掉,验证如下:

在上述的测试类中加入反序列的代码,如下所示:

 serializable(enum_Sington.getInstance());private static void  serializable(Object instance) throws IOException, ClassNotFoundException {ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream();ObjectOutputStream objectOutputStream=new ObjectOutputStream(byteArrayOutputStream);//通过writeObject将获取到的对象转变为字节流objectOutputStream.writeObject(instance);ObjectInputStream objectInputStream=new ObjectInputStream(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));//通过readObject将转变后的字节流还原成对象System.out.println("反序列化创建实例:"+objectInputStream.readObject());}

输出:

private enum_Sington()
otherMethod()
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
enum_Sington@7ef20235
enum_Sington@7ef20235
反序列化创建实例:enum_Sington@7ef20235

通过输出结果,我们会发现,反序列化创建的对象和上述枚举类创建的对象是同一个

那么反射可以破坏吗?

验证如下:

reflection(enum_Sington.class);
private static void reflection(Class<?> classz) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {//通过getDeclaredConstructor获得私有构造Constructor<?> constructor=classz.getDeclaredConstructor();//通过setAccessible使得私有的构造方法也可以被使用constructor.setAccessible(true);System.out.println("反射创建实例:"+constructor.newInstance());}

在这里插入图片描述

newInstance实例化对象只能调用无参构造方法(如果重写了一个带参构造方法,想要使用newInstance,则必须指定一个无参构造方法,否则会报初始化错误)

在这里插入图片描述

懒汉式实现:

import java.io.Serializable;public class Singleton3 implements Serializable {private Singleton3(){System.out.println("private Singleton3()");}private static Singleton3 INSTACE =null;//开始将其置为null,当要使用它时,才创建该对象public static Singleton3 getInstance() {if (INSTACE == null) {INSTACE = new Singleton3();}return INSTACE;}public static void otherMethod() {System.out.println("otherMethod()");}
}
class Test_Singleton1 {public static void main(String[] args) {//INSTACE对象此时还不会被创建Singleton3.otherMethod();System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");//当调用getISTACE方法时,INSTACE对象才会被创建System.out.println(Singleton3.getInstance());System.out.println(Singleton3.getInstance());}
}
otherMethod()
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
private Singleton3()
Singleton3@7ef20235
Singleton3@7ef20235

但懒汉式会出现一个问题,也就是不加线程的保护下,多个线程都可以调用getINSTACE方法,那么当多线程调用这个方法时,就会出现下述问题:

线程1首次调用getINSATCE方法,发现INSTACE是null没有被创建,因此进行创建,当线程1执行到if语句中的代码时,线程二也调用该方法,假设此时线程1还没有完成将刚创建好的对象赋值给INSTACE的这个操作,就会出现当线程2调用该方法时,INSTACE显示还是为null,它也会创建新的INSTACE对象,此时就不能被称为是单例了

在这里插入图片描述

这就是我们在多线程环境下执行单例存在的问题,那么该如何解决呢?

给getInstance方法加安全保护,也就是用sychronized进行修饰,其原理就是给该方法加锁

当加锁后的运行过程如下所示:

在这里插入图片描述
在这里插入图片描述

当线程2获得使用权后,进入该方法,发现INSTCE不为null,则不进行该对象的创建,直接返回前面线程1已经创建好的INSTCE对象,这样就能有效的避免多线程下单例模式的正确运行

但这样做的性能并不是最好的,原因是:我们加锁的目的就是为了防止INSTACE被多次创建,这样虽然能够解决首次仅由一个线程创建该对象,但当下次调用该方法的时候,加锁似乎没什么意义,因为对象已经被创建出来了

我们理想的目标是首次调用该方法加锁,而后续调用不加锁

优化方法——使用双检锁:

在这里插入图片描述

注意:

在这里插入图片描述

使用双检锁的INSTACE对象必须用volatile关键字修饰:主要利用内存屏障,保证有序性,在多线程下防止发生指令重排序

private static  volatile Singleton3 INSTACE =null;

内部类实现懒汉式单例:

发生在懒汉式中的多线程安全问题并没有出现在饿汉式实现单例中,原因是我们将其INSTACE对象的创建赋值给了static修饰的变量,而被static修饰的代码最终都会放在静态代码块中执行,而静态代码块中的线程安全并不需要我们去考虑,java虚拟机会帮我们保证其安全

那我们只需想办法将懒汉式中的INSTACE对象创建过程放在一个静态的代码块中即可,如下所示:

内部类也是符合懒汉式的特征,如果内部类没有被使用,那么类的加载链接初始化过程也不会发生,自然写在其中的INSTACE也不会被重复创建,那么什么时候会使用到它呢?

就是调用getInstace方法的时候,因此我们只需要将类的使用过程写在getInstace方法中

import java.io.Serializable;public class Singleton3 implements Serializable {private Singleton3(){System.out.println("private Singleton3()");}private static class Holder {static Singleton3 INSTACE=new Singleton3();}public static Singleton3 getInstance(){return Holder.INSTACE;}public static void otherMethod() {System.out.println("otherMethod()");}
}
class Test_Singleton1 {public static void main(String[] args) {//触发当前类的加载链接--导致该类的初始化操作被创建,当我们调用otherMethod()方法时,该类已经被创建,因为在输出的内容中,包含该类私有构造中的内容Singleton3.otherMethod();System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");//下面我们调用getInstance()方法时,得到的对象为上述已经创建好的对象System.out.println(Singleton3.getInstance());System.out.println(Singleton3.getInstance());}
}

上述使用内部类的懒汉式,也正是我们所推荐的,不仅符合懒汉式的特征,而且可以保证线程安全

相关文章:

设计模式之单例模式~

设计模式包含很多&#xff0c;但与面试相关的设计模式是单例模式&#xff0c;单例模式的写法有好几种&#xff0c;我们主要学习这三种—饿汉式单例&#xff0c;懒汉式单例、登记式单例,这篇文章我们主要学习饿汉式单例 单例模式&#xff1a; 满足要点&#xff1a; 私有构造 …...

top终端详解

1.top命令行使用 2.top每行意义 3.补充 1.top命令行使用 top命令是一个常用的Linux系统命令&#xff0c;用于实时查看系统的运行状态和进程信息。下面是top命令的几个常用参数的含义&#xff1a; -d seconds&#xff1a;设置top命令的更新间隔时间&#xff0c;单位是秒。默认是…...

解决一个偶现的503 bug,花了俺不少时间

概述 在3月2日晚上&#xff0c;大概8点左右&#xff0c;本想打道回府&#xff0c;回家休息&#xff0c;突然被人在bug群了一下&#xff0c;说是管理后台&#xff0c;访问不了&#xff0c;界面上出现了: 503 service temporarily unavailable我赶紧尝试访问了一下&#xff0c;确…...

什么是栈,如何实现?

欢迎来到 Claffic 的博客 &#x1f49e;&#x1f49e;&#x1f49e; “但有一枝堪比玉&#xff0c;何须九畹始征兰?” 前言&#xff1a; 栈是一种特殊的线性表&#xff0c;就像开盖的桶一样&#xff0c;从底部开始放数据&#xff0c;从顶部开始取数据&#xff0c;那么栈具体是…...

在我的MacBook上捣鼓ESP8266

周三是我们的篮球日&#xff0c;打篮球后总是会有些兴奋&#xff0c;然后就容易睡不着&#xff0c;额&#xff0c;睡不着就拿我的ESP8266开发板出来捣鼓一下。先下载编译工具链https://github.com/espressif/ESP8266_RTOS_SDK下载sdkgit clone https://github.com/espressif/ES…...

【深度强化学习】(8) iPPO 模型解析,附Pytorch完整代码

大家好&#xff0c;今天和各位分享一下多智能体深度强化学习算法 ippo&#xff0c;并基于 gym 环境完成一个小案例。完整代码可以从我的 GitHub 中获得&#xff1a;https://github.com/LiSir-HIT/Reinforcement-Learning/tree/main/Model 1. 算法原理 多智能体的情形相比于单智…...

77.qt qml-QianWindow-V1版本界面讲解

上章介绍: 76.qt qml-QianWindow开源炫酷界面框架简介(支持白色暗黑渐变自定义控件均以适配) 界面如下所示: 代码结构如下所示:...

RHCE学习日记二

1、在 node1 主机上配置 chrony 时间服务器&#xff0c;将该主机作为时间服务器。 命令&#xff1a; vim /etc/chrony.conf 在文件位置添加命令&#xff1a; #Use public servers from the pool.ntp.org project. #Please consider joining the pool (https://www.pool.ntp.org…...

Dubbo原理简介

Dubbo缺省协议采用单一长连接和NIO异步通讯&#xff0c;适合于小数据量大并发的服务调用&#xff0c;以及服务消费者机器数远大于服务提供者机器数的情况。 作为RPC&#xff1a;支持各种传输协议&#xff0c;如dubbo,hession,json,fastjson&#xff0c;底层采用mina,netty长连接…...

JavaSE基础总结

JDK与JRE JDK&#xff0c;全称Java Development Kit&#xff0c;Java开发工具包 JRE&#xff0c;全称Java Runntime Environment&#xff0c;Java运行环境 JDK包含后者JRE。 JDK也可以说是Java SDK&#xff08;Software Development kit&#xff0c;软件开发工具包&#xff09;…...

5G(NR)信道带宽和发射带宽---频率资源

前言 查看此文之前建议先看看这篇 5G(NR)频率资源划分_nr运营商频段划分_达帮主的博客-CSDN博客NR频率有上面几个划分 &#xff0c;可以使用低于1GHz的频端&#xff0c;既可以使用高于30GHz高频端。使用频端高于30GHz那我们称之为高频或者毫米波。使用毫米波是5G网络区别于4G…...

基于Spring Boot的酒店管理系统

文章目录 项目介绍主要功能截图:登录首页房间类型酒店预约部分代码展示设计总结项目获取方式🍅 作者主页:Java韩立 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 🍅文末获取源码联系🍅 项目介绍 基于Spring Boot的酒店管理系统…...

Ae:混合模式

Ae 中内置了 Ps 的渲染引擎&#xff0c;同样可在多处应用混合模式 Blending Mode。与 Ps 相比&#xff0c;除了两组图层通道相关的特定模式&#xff0c;其它的混合模式几乎是一模一样。相关快捷键&#xff1a;下一图层混合模式&#xff1a;Shift 上一图层混合模式&#xff1a;…...

JS中的变量

系列文章目录 前端系列文章——传送门 JavaScript系列文章——传送门 文章目录系列文章目录前言1、概念2、定义变量3、变量名的规则4、变量本质5、赋值6、常用操作前言 相对于青龙面板来说&#xff0c;变量就是你填入青龙的cookie&#xff0c;简称ck 在实际项目中&#xff0…...

Hadoop运行模块

二、Hadoop运行模式 1&#xff09;Hadoop官方网站&#xff1a;http://hadoop.apache.org 2&#xff09;Hadoop运行模式包括&#xff1a;本地模式、伪分布式模式以及完全分布式模式。 本地模式&#xff1a;单机运行&#xff0c;只是用来演示一下官方案例。生产环境不用。伪分…...

Web自动化——前端基础知识(二)

1. Web前端开发三要素 web前端开发三要素 什么是HTMl&#xff1f; Html是超文本标记语言&#xff0c;是用来描述网页的一种标记语言HTML是一种标签规则的形式将内容呈现在浏览器中可以以任意编辑器创建&#xff0c;其文件扩展名为.html或.htm保存即可 什么是CSS&#xff1f;…...

NAS系列 硬件组装

转自我的博客文章https://blognas.hwb0307.com/nas/3260&#xff0c;内容更新仅在个人博客可见。欢迎关注&#xff01; 前言 之前我在《NAS系列 硬件选择》里讲述了自己为了升级NAS如何选配硬件。本节我大概说一些我的新NAS硬件组装的注意事项。到目前为止&#xff0c;我只装过…...

IDAFrida

IDA&Frida 前言 偶然间发现了一本秘籍《IDA脚本开发之旅》&#xff0c;这是白龙的系列文章&#xff0c;主要是安卓平台&#xff0c;笔者只是根据他的知识点学习&#xff0c;拓展&#xff0c;可以会稍微提及别的平台。本文并不会贴出他的思路分析&#xff0c;只对于源码进…...

通过百度文心一言大模型作画尝鲜,感受国产ChatGPT的“狂飙”

3月16日下午&#xff0c;百度于北京总部召开新闻发布会&#xff0c;主题围绕新一代大语言模型、生成式AI产品文心一言。百度创始人、董事长兼首席执行官李彦宏&#xff0c;百度首席技术官王海峰出席&#xff0c;并展示了文心一言在文学创作、商业文案创作、数理推算、中文理解、…...

Nacos 注册中心 - 健康检查机制源码

目录 1. 健康检查介绍 2. 客户端健康检查 2.1 临时实例的健康检查 2.2 永久实例的健康检查 3. 服务端健康检查 3.1 临时实例的健康检查 3.2 永久实例服务端健康检查 1. 健康检查介绍 当一个服务实例注册到 Nacos 中后&#xff0c;其他服务就可以从 Nacos 中查询出该服务…...

RestClient

什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端&#xff0c;它允许HTTP与Elasticsearch 集群通信&#xff0c;而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级&#xff…...

Docker 离线安装指南

参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性&#xff0c;不同版本的Docker对内核版本有不同要求。例如&#xff0c;Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本&#xff0c;Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

Linux 文件类型,目录与路径,文件与目录管理

文件类型 后面的字符表示文件类型标志 普通文件&#xff1a;-&#xff08;纯文本文件&#xff0c;二进制文件&#xff0c;数据格式文件&#xff09; 如文本文件、图片、程序文件等。 目录文件&#xff1a;d&#xff08;directory&#xff09; 用来存放其他文件或子目录。 设备…...

Leetcode 3576. Transform Array to All Equal Elements

Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接&#xff1a;3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到&#xf…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》

引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...

深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法

深入浅出&#xff1a;JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中&#xff0c;随机数的生成看似简单&#xff0c;却隐藏着许多玄机。无论是生成密码、加密密钥&#xff0c;还是创建安全令牌&#xff0c;随机数的质量直接关系到系统的安全性。Jav…...

服务器硬防的应用场景都有哪些?

服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式&#xff0c;避免服务器受到各种恶意攻击和网络威胁&#xff0c;那么&#xff0c;服务器硬防通常都会应用在哪些场景当中呢&#xff1f; 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...

爬虫基础学习day2

# 爬虫设计领域 工商&#xff1a;企查查、天眼查短视频&#xff1a;抖音、快手、西瓜 ---> 飞瓜电商&#xff1a;京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空&#xff1a;抓取所有航空公司价格 ---> 去哪儿自媒体&#xff1a;采集自媒体数据进…...

【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)

1.获取 authorizationCode&#xff1a; 2.利用 authorizationCode 获取 accessToken&#xff1a;文档中心 3.获取手机&#xff1a;文档中心 4.获取昵称头像&#xff1a;文档中心 首先创建 request 若要获取手机号&#xff0c;scope必填 phone&#xff0c;permissions 必填 …...

Elastic 获得 AWS 教育 ISV 合作伙伴资质,进一步增强教育解决方案产品组合

作者&#xff1a;来自 Elastic Udayasimha Theepireddy (Uday), Brian Bergholm, Marianna Jonsdottir 通过搜索 AI 和云创新推动教育领域的数字化转型。 我们非常高兴地宣布&#xff0c;Elastic 已获得 AWS 教育 ISV 合作伙伴资质。这一重要认证表明&#xff0c;Elastic 作为 …...