【JVM】总结篇-类的加载篇之 类的加载器 和ClassLoader分析

文章目录

    • 类的加载器
    • ClassLoader
    • 自定义类加载器
    • 双亲委派机制
      • 概念
      • 源码分析
      • 优势劣势
      • 如何打破
      • Tomcat
    • 沙箱安全机制
    • JDK9 双亲委派机制变化

类的加载器

在这里插入图片描述

获得当前类的ClassLoader clazz.getClassLoader()
获得当前线程上下文的ClassLoader Thread.currentThread().getContextClassLoader()
获得系统的ClassLoader ClassLoader.getSystemClassLoader()

ClassLoader

在这里插入图片描述
抽象类ClassLoader的主要方法:(内部没有抽象方法)

public final ClassLoader getParent()
返回该类加载器的超类加载器
public Class<?> loadClass(String name) throws ClassNotFoundException
加载名称为name的类,返回结果为java.lang.Class类的实例。
如果找不到类,则返回 ClassNotFoundException 异常。该方法中的逻辑就是双亲委派模式的实现。
protected Class<?> findClass(String name) throws ClassNotFoundException
查找二进制名称为name的类,返回结果为java.lang.Class类的实例。这是一个受保护的方法,
JVM鼓励我们重写此方法,需要自定义加载器遵循双亲委托机制,
该方法会在检查完父类加载器之后被loadClass()方法调用。

在JDK1.2之前,在自定义类加载时,总会去继承ClassLoader类并重写loadClass方法,从而实现自定义的类加载类。但是在JDK1.2之后已不再建议用户去覆盖loadClass()方法,而是建议把自定义的类加载逻辑写在findClass()方法中,从前面的分析可知,findClass()方法是在loadClass()方法中被调用的,当loadClass()方法中父加载器加载失败后,则会调用自己的findClass()方法来完成类加载,这样就可以保证自定义的类加载器也符合双亲委托模式。
需要注意的是ClassLoader类中并没有实现findClass()方法的具体代码逻辑,取而代之的是抛出ClassNotFoundException异常,同时应该知道的是findClass方法通常是和defineClass方法一起使用的。一般情况下,在自定义类加载器时,会直接覆盖ClassLoader的findClass()方法并编写加载规则,取得要加载类的字节码后转换成流,然后调用defineClass()方法生成类的Class对象。

protected final Class<?> defineClass(String name, byte[] b, int off, int len)
根据给定的字节数组b转换为Class的实例,off和len参数表示实际Class信息在byte数组中的位置和长度,
其中byte数组b是ClassLoader从外部获取的。这是受保护的方法,只有在自定义ClassLoader子类中可以使用。

defineClass()方法是用来将byte字节流解析成JVM能够识别的Class对象(ClassLoader中已实现该方法逻辑),通过这个方法不仅能够通过class文件实例化class对象,也可以通过其他方式实例化class对象,如通过网络接收一个类的字节码,然后转换为byte字节流创建对应的Class对象。
defineClass()方法通常与findClass()方法一起使用,一般情况下,在自定义类加载器时,会直接覆盖ClassLoader的findClass()方法并编写加载规则,取得要加载类的字节码后转换成流,然后调用defineClass()方法生成类的Class对象

简单举例:

protected Class<?> findClass(String name) throws ClassNotFoundException {// 获取类的字节数组byte[] classData = getClassData(name);if (classData == null) {throw new ClassNotFoundException();} else {//使用defineClass生成class对象return defineClass(name, classData, 0, classData.length);}
}
protected final void resolveClass(Class<?> c)
链接指定的一个Java类。使用该方法可以使用类的Class对象创建完成的同时也被解析。
前面我们说链接阶段主要是对字节码进行验证,
为类变量分配内存并设置初始值同时将字节码文件中的符号引用转换为直接引用。
protected final Class<?> findLoadedClass(String name)
查找名称为name的已经被加载过的类,返回结果为java.lang.Class类的实例。这个方法是final方法,无法被修改。
 private final ClassLoader parent;
它也是一个ClassLoader的实例,这个字段所表示的ClassLoader也称为这个ClassLoader的双亲。
在类加载的过程中,ClassLoader可能会将某些请求交予自己的双亲处理。

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

自定义类加载器

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


public class UserClassLoader extends ClassLoader {private String rootDir;public UserClassLoader(String rootDir) {this.rootDir = rootDir;}/*** 编写findClass方法的逻辑*/@Overrideprotected Class<?> findClass(String name) throws ClassNotFoundException {// 获取类的class文件字节数组byte[] classData = getClassData(name);if (classData == null) {throw new ClassNotFoundException();} else {//直接生成class对象return defineClass(name, classData, 0, classData.length);}}/*** 编写获取class文件并转换为字节码流的逻辑 * @param className * @return*/private byte[] getClassData(String className) {// 读取类文件的字节String path = classNameToPath(className);try {InputStream ins = new FileInputStream(path);ByteArrayOutputStream baos = new ByteArrayOutputStream();byte[] buffer = new byte[1024];int len = 0;// 读取类文件的字节码while ((len = ins.read(buffer)) != -1) {baos.write(buffer, 0, len);}return baos.toByteArray();} catch (IOException e) {e.printStackTrace();}return null;}/*** 类文件的完全路径*/private String classNameToPath(String className) {return rootDir + "\\" + className.replace('.', '\\') + ".class";}public static void main(String[] args) {String rootDir = "D:\\Java_course\\JVM\\JVMdachang\\chapter02_classload\\src\\";try {//创建自定义的类的加载器1UserClassLoader loader1 = new UserClassLoader(rootDir);Class clazz1 = loader1.findClass("com.cz.java3.User");//创建自定义的类的加载器2UserClassLoader loader2 = new UserClassLoader(rootDir);Class clazz2 = loader2.findClass("com.cz.java3.User");System.out.println(clazz1 == clazz2); //clazz1与clazz2对应了不同的类模板结构。System.out.println(clazz1.getClassLoader());System.out.println(clazz2.getClassLoader());//######################Class clazz3 = ClassLoader.getSystemClassLoader().loadClass("com.cz.java3.User");System.out.println(clazz3.getClassLoader());System.out.println(clazz1.getClassLoader().getParent());} catch (ClassNotFoundException e) {e.printStackTrace();}}}
false
com.atguigu.java3.UserClassLoader@14ae5a5
com.atguigu.java3.UserClassLoader@6d6f6e28
sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$AppClassLoader@18b4aac2

双亲委派机制

双亲委派好处有哪些?(亚信)
类加载器双亲委派模型机制?(苏宁)
双亲委派机制 (蚂蚁金服)
双亲委派机制及使用原因 (蚂蚁金服)
类加载器的双亲委派模型是什么? (蚂蚁金服)
双亲委派模型介绍一下 (小米)
讲一下双亲委派模型,以及其优点 (滴滴)
类加载器的双亲委派模型是什么? (京东)

概念

1.定义
如果一个类加载器在接到加载类的请求时,它首先不会自己尝试去加载这个类,而是把这个请求任务委托给父类加载器去完成,依次递归,如果父类加载器可以完成类加载任务,就成功返回。只有父类加载器无法完成此加载任务时,才自己去加载。

2.本质
规定了类加载的顺序是:引导类加载器先加载,若加载不到,由扩展类加载器加载,若还加载不到,才会由系统类加载器或自定义的类加载器进行加载。

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

源码分析

protected Class<?> loadClass(String name, boolean resolve)throws ClassNotFoundException{synchronized (getClassLoadingLock(name)) {// First, check if the class has already been loadedClass<?> c = findLoadedClass(name);if (c == null) {long t0 = System.nanoTime();try {if (parent != null) {c = parent.loadClass(name, false);} else {c = findBootstrapClassOrNull(name);}} catch (ClassNotFoundException e) {// ClassNotFoundException thrown if class not found// from the non-null parent class loader}if (c == null) {// If still not found, then invoke findClass in order// to find the class.long t1 = System.nanoTime();c = findClass(name);// this is the defining class loader; record the statssun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);sun.misc.PerfCounter.getFindClasses().increment();}}if (resolve) {resolveClass(c);}return c;}}

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

优势劣势

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

如何打破

双亲委派机制可以打破吗?为什么 (京东)
可以打破双亲委派么,怎么打破。(拼多多)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Tomcat

什么是tomcat类加载机制?(猎聘)
请解释tomcat的类加载机制?(阿里)

Tomcat8 和 Tomcat6比较大的区别是 :
Tomcat8可以通过配置 表示遵循双亲委派机制。

Tomcat的类加载机制是违反了双亲委托原则的,对于一些未加载的非基础类,各个web应用自己的类加载器(WebAppClassLoader)会优先查看自己的仓库加载,加载不到时再交给commonClassLoader走双亲委托。

Tomcat 如何实现自己独特的类加载机制?
在这里插入图片描述
当tomcat启动时,会创建几种类加载器:

  1. Bootstrap 引导类加载器
    加载JVM启动所需的类,以及标准扩展类(位于jre/lib/ext下)
  2. System 系统类加载器
    加载tomcat启动的类,比如bootstrap.jar,通常在catalina.bat或者catalina.sh中指定。位于CATALINA_HOME/bin下。
    在这里插入图片描述
  3. CommonClassLoader、CatalinaClassLoader、SharedClassLoader和WebappClassLoader
    这些是Tomcat自己定义的类加载器,它们分别加载/common/、/server/、/shared/*(在tomcat 6之后已经合并到根目录下的lib目录下)和/WebApp/WEB-INF/*中的Java类库。其中WebApp类加载器和Jsp类加载器通常会存在多个实例,每一个Web应用程序对应一个WebApp类加载器,每一个JSP文件对应一个Jsp类加载器。
    commonLoader:Tomcat最基本的类加载器,加载路径中的class可以被Tomcat容器本身以及各个Webapp访问;(加载CATALINA_HOME/lib下的结构,比如servlet-api.jar)
    catalinaLoader:Tomcat容器私有的类加载器,加载路径中的class对于Webapp不可见;
    sharedLoader:各个Webapp共享的类加载器,加载路径中的class对于所有Webapp可见,但是对于Tomcat容器不可见;
    WebappClassLoader:单个Tomcat实例中各个Web应用程序私有的类加载器,加载路径中的class只对当前Webapp可见;(加载WEB-INF/lib和WEB-INF/classes下的结构)

从图中的委派关系中可以看出:
CommonClassLoader能加载的类都可以被Catalina ClassLoader和SharedClassLoader使用,从而实现了公有类库的共用,而CatalinaClassLoader和Shared ClassLoader自己能加载的类则与对方相互隔离。
WebAppClassLoader可以使用SharedClassLoader加载到的类,但各个WebAppClassLoader实例之间相互隔离。
而JasperLoader的加载范围仅仅是这个JSP文件所编译出来的那一个.class文件,它出现的目的就是为了被丢弃:当Web容器检测到JSP文件被修改时,会替换掉目前的JasperLoader的实例,并通过再建立一个新的Jsp类加载器来实现JSP文件的HotSwap功能。

当应用需要到某个类时,则会按照下面的顺序进行类加载:
1 使用bootstrap引导类加载器加载
2 使用system系统类加载器加载
3 使用应用类加载器在WEB-INF/classes中加载
4 使用应用类加载器在WEB-INF/lib中加载
5 使用common类加载器在CATALINA_HOME/lib中加载

在这里插入图片描述
好了,至此,我们已经知道了tomcat为什么要这么设计,以及是如何设计的,那么,tomcat 违背了java 推荐的双亲委派模型了吗?答案是:违背了。 我们前面说过:双亲委派模型要求除了顶层的启动类加载器之外,其余的类加载器都应当由自己的父类加载器加载。
很显然,tomcat 不是这样实现,tomcat 为了实现隔离性,没有遵守这个约定,每个webappClassLoader加载自己的目录下的class文件,不会传递给父类加载器。

Tomcat中WebappClassLoader的源码分析:

 1 public Class loadClass(String name, boolean resolve)2             throws ClassNotFoundException {3         Class clazz = null;4         // (0) 先从自己的缓存中查找,有则返回,无则继续5         clazz = findLoadedClass0(name);6         if (clazz != null) {7             if (resolve) resolveClass(clazz);            8             return (clazz);9         }
10         // (0.1) 再从parent的缓存中查找
11         clazz = findLoadedClass(name);
12         if (clazz != null) {
13             if (resolve) resolveClass(clazz);
14             return (clazz);
15         }
16         // (0.2) 缓存中没有,则首先使用system类加载器来加载
17         clazz = system.loadClass(name);
18          if (clazz != null) {
19              if (resolve) resolveClass(clazz);
20              return (clazz);
21          }
22         //判断是否需要先让parent代理
23         boolean delegateLoad = delegate || filter(name);
24         // (1) 先让parent加载,通常delegateLoad == false,即这一步不会执行
25 
26         if (delegateLoad) {
27             ClassLoader loader = parent;
28             if (loader == null)
29                 loader = system;
30             clazz = loader.loadClass(name);
31             if (clazz != null) {
32                 if (resolve) resolveClass(clazz);
33                 return (clazz);
34             }
35         }
36         // (2) delegateLoad == false 或者 parent加载失败,调用自身的加载机制
37         clazz = findClass(name);
38         if (clazz != null) {
39             if (resolve) resolveClass(clazz);
40             return (clazz);
41         }
42         // (3) 自己加载失败,则请求parent代理加载
43 
44         if (!delegateLoad) {
45             ClassLoader loader = parent;
46             if (loader == null)
47                 loader = system;
48             clazz = loader.loadClass(name);
49             if (clazz != null) {
50                 return (clazz);
51             }
52         }
53         throw new ClassNotFoundException(name);
54     }

总结一下:
首先findLoadedClass0()和findLoadedClass()分别从本地和父类加载器的缓存中查找当前要加载的类是否已经加载过了。之后为了避免上面提到的安全问题,Tomcat类加载器会将加载请求委派给系统类加载器。接下来根据delegate变量的设置,决定是先由自己加载,还是先由父类加载器去加载。

1、既然 Tomcat 不遵循双亲委派机制,那么如果我自己定义一个恶意的HashMap,会不会有风险呢?(阿里面试问题)
答: 显然不会有风险,如果有,Tomcat都运行这么多年了,那能不改进吗?
tomcat不遵循双亲委派机制,只是自定义的classLoader顺序不同,但顶层还是相同的,还是要去顶层请求classloader。

2、我们思考一下:Tomcat是个web容器, 那么它要解决什么问题?

  1. 一个web容器可能需要部署两个应用程序,不同的应用程序可能会依赖同一个第三方类库的不同版本,不能要求同一个类库在同一个服务器只有一份,因此要保证每个应用程序的类库都是独立的,保证相互隔离。
  2. 部署在同一个web容器中相同的类库相同的版本可以共享。否则,如果服务器有10个应用程序,那么要有10份相同的类库加载进虚拟机,这是扯淡的。
  3. web容器也有自己依赖的类库,不能于应用程序的类库混淆。基于安全考虑,应该让容器的类库和程序的类库隔离开来。
  4. web容器要支持jsp的修改,我们知道,jsp 文件最终也是要编译成class文件才能在虚拟机中运行,但程序运行后修改jsp已经是司空见惯的事情,否则要你何用? 所以,web容器需要支持 jsp 修改后不用重启。

3、Tomcat 如果使用默认的类加载机制行不行?
答案是不行的。为什么?我们看:
第一个问题,如果使用默认的类加载器机制,那么是无法加载两个相同类库的不同版本的,默认的累加器是不管你是什么版本的,只在乎你的全限定类名,并且只有一份。
第二个问题,默认的类加载器是能够实现的,因为他的职责就是保证唯一性。
第三个问题和第一个问题一样。
我们再看第四个问题,我们想我们要怎么实现jsp文件的热替换,jsp 文件其实也就是class文件,那么如果修改了,但类名还是一样,类加载器会直接取方法区中已经存在的,修改后的jsp是不会重新加载的。那么怎么办呢?我们可以直接卸载掉这jsp文件的类加载器,所以你应该想到了,每个jsp文件对应一个唯一的类加载器,当一个jsp文件修改了,就直接卸载这个jsp类加载器。重新创建类加载器,重新加载jsp文件。

4、如果tomcat 的 Common ClassLoader 想加载 WebApp ClassLoader 中的类,该怎么办?
看了前面的关于破坏双亲委派模型的内容,我们心里有数了,我们可以使用线程上下文类加载器实现,使用线程上下文加载器,可以让父类加载器请求子类加载器去完成类加载的动作。

5、为什么java文件放在Eclipse/IDEA中的src文件夹下会优先jar包中的class?
tomcat类加载机制的理解,就不难明白。因为Eclipse/IDEA中的src文件夹中的文件java以及webContent中的JSP都会在tomcat启动时,被编译成class文件放在 WEB-INF/class 中。
而Eclipse/IDEA外部引用的jar包,则相当于放在 WEB-INF/lib 中。
因此肯定是 java文件或者JSP文件编译出的class优先加载。

沙箱安全机制

保证程序安全
保护Java原生的JDK代码

沙箱机制就是将Java代码限定在虚拟机(JVM)特定的运行范围中,并且严格限制代码对本地系统资源访问。
通过这样的措施来保证对代码的有限隔离,防止对本地系统造成破坏。

JDK9 双亲委派机制变化

在这里插入图片描述

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

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

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

相关文章

数据挖掘——回归算法

数据挖掘——回归算法 回归算法线性回归最小二乘法优化求解——梯度下降法逻辑回归逻辑回归函数逻辑回归参数估计逻辑回归正则化 决策树回归小结 回归算法 回归分析 如果把其中的一些因素&#xff08;房屋面积&#xff09;作为自变量&#xff0c;而另一些随自变量的变化而变化…

前端如何从入门进阶到高级

在前端学习的道路上&#xff0c;我们将其划分为三个阶段&#xff1a;入门、实战和进阶。以下是各阶段的学习指南 一、入门阶段 在入门阶段&#xff0c;我们的目标是掌握前端的基本语法和知识&#xff0c;以便能够独立解决一些基础问题。这一阶段&#xff0c;我们建议通过视频…

Android14 CTS-R6和GTS-12-R2不能同时测试的解决方法

背景 Android14 CTS r6和GTS 12-r1之后&#xff0c;tf-console默认会带起OLC Server&#xff0c;看起来olc server可能是想适配ATS(android-test-station)&#xff0c;一种网页版可视化、可配置的跑XTS的方式。这种网页版ATS对测试人员是比较友好的&#xff0c;网页上简单配置下…

Linux中的tcpdump抓包命令详解:抓取TCP和UDP数据包并按小时输出文件

Linux中的tcpdump抓包命令详解:抓取TCP和UDP数据包并按小时输出文件 一、tcpdump简介二、安装tcpdump三、抓取TCP和UDP数据包四、按小时输出文件五、tcpdump命令的常用选项和表达式六、总结在Linux系统中,tcpdump是一款强大的网络抓包工具,它基于libpcap库开发,可以捕获网络…

k8s基础(4)—Kubernetes-Service

Service概述 抽象层 ‌k8s的Service是一种抽象层&#xff0c;用于为一组具有相同功能的Pod提供一个统一的入口地址&#xff0c;并通过负载均衡将网络流量分发到这些Pod上。‌ Service解决了Pod动态变化的问题&#xff0c;例如Pod的IP地址和端口可能会发生变化&#xff0c;通过…

国内Ubuntu环境Docker部署CosyVoice

国内Ubuntu环境Docker部署CosyVoice 本文旨在记录在 国内 CosyVoice项目在 Ubuntu 环境下如何使用 dockermin-conda进行一键部署。 源项目地址&#xff1a; https://github.com/FunAudioLLM/CosyVoice 如果想要使用 dockerpython 进行部署&#xff0c;可以参考我另一篇博客中的…

基于 gitlab-runner 实现调度GPU的资源

本篇目录 1. 客户需求2. 需求调研3. 实践3.1 方案一&#xff1a;环境变量的方式3.2 方案二&#xff1a;k8s 自身的spec注入机制 4. 效果 该实践来自于客户的一个真实需求 1. 客户需求 客户的某些流水线需要使用GPU资源&#xff0c;但是对于GPU服务器而言&#xff0c;会有多张G…

计算机网络 —— 网络编程(TCP)

计算机网络 —— 网络编程&#xff08;TCP&#xff09; TCP和UDP的区别TCP (Transmission Control Protocol)UDP (User Datagram Protocol) 前期准备listen &#xff08;服务端&#xff09;函数原型返回值使用示例注意事项 accpect &#xff08;服务端&#xff09;函数原型返回…

模型 九屏幕分析法

系列文章 分享 模型&#xff0c;了解更多&#x1f449; 模型_思维模型目录。九屏幕法&#xff1a;全方位分析问题的系统工具。 1 九屏幕分析法的应用 1.1 新产品研发的市场分析 一家科技公司计划开发一款新型智能手机&#xff0c;为了全面评估市场潜力和风险&#xff0c;他们…

Unity2D初级背包设计中篇 MVC分层撰写(万字详解)

本人能力有限&#xff0c;如有不足还请斧正&#xff0c;理论分析链接如下&#xff1a; Unity2D初级背包设计前篇 理论分析-CSDN博客 目录 1.M层&#xff1a;数据存储 物品 仓库容器 加载方式 2.M层&#xff1a;逻辑撰写 InventoryManager 仓库的管理 SlotData 物品的增…

深入理解 Linux 管道:创建与应用详解(匿名管道进程池)

在现代操作系统中&#xff0c;进程间通信&#xff08;IPC&#xff09;是实现多任务、多进程协作的关键技术之一。Linux 提供了多种 IPC 机制&#xff0c;本博客将帮助您详细的理解进程间通信的原理 首先&#xff0c;在学习管道之前&#xff0c;我们先理解一下管道的存在是为了什…

SWM221系列芯片之电机应用及控制

经过对SWM221系列的强大性能及外设资源&#xff0c;TFTLCD彩屏显示及控制进行了整体介绍后&#xff0c;新迎来我们的电控篇---SWM221系列芯片之电机应用及控制。在微控制器市场面临性能、集成度与成本挑战的当下&#xff0c;SWM221系列芯片以其卓越性能与创新设计&#xff0c;受…

Trimble天宝X9三维扫描仪为建筑外墙检测提供了全新的解决方案【沪敖3D】

随着城市化进程的快速推进&#xff0c;城市高层建筑不断增多&#xff0c;对建筑质量的要求也在不断提高。建筑外墙检测&#xff0c;如平整度和垂直度检测&#xff0c;是衡量建筑质量的重要指标之一。传统人工检测方法不仅操作繁琐、效率低下&#xff0c;还难以全面反映墙体的真…

机器人手眼标定

机器人手眼标定 一、机器人手眼标定1. 眼在手上标定基本原理2. 眼在手外标定基本原理 二、眼在手外标定实验三、标定精度分析 一、机器人手眼标定 要实现由图像目标点到实际物体上抓取点之间的坐标转换&#xff0c;就必须拥有准确的相机内外参信息。其中内参是相机内部的基本参…

unity中的UI系统---GUI

一、工作原理和主要作用 1.GUI是什么&#xff1f; 即即时模式游戏用户交互界面&#xff08;IMGUI&#xff09;&#xff0c;在unity中一般简称为GUI&#xff0c;它是一个代码驱动的UI系统。 2.GUI的主要作用 2.1作为程序员的调试工具&#xff0c;创建游戏内调测试工具 2.2为…

Java开发 PDF文件生成方案

业务需求背景 业务端需要能够将考试答卷内容按指定格式呈现并导出为pdf格式进行存档&#xff0c;作为紧急需求插入。导出内容存在样式复杂性&#xff0c;包括特定的字体&#xff08;中文&#xff09;、字号、颜色&#xff0c;页面得有页眉、页码&#xff0c;数据需要进行表格聚…

SpringCloud微服务架构

文章目录 认识微服务&#xff1a;SpringCloud 服务拆分及远程调用实现夸远程服务调用使用RestTemplateEureka注册中心 搭建EruekaServer注册服务服务发现 Ribbon负载均衡 修改负载均衡规则解饿加载 Nacos注册中心&#xff08;nacos一部分功能&#xff09; 服务注册到nacosnacos…

【设计模式-02】23 种设计模式的分类和功能

在软件工程领域&#xff0c;设计模式是解决常见设计问题的经典方案。1994 年&#xff0c;Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides&#xff08;四人帮&#xff0c;GoF&#xff09;在《设计模式&#xff1a;可复用面向对象软件的基础》一书中系统性地总结了…

简历_专业技能_熟悉分布式锁Redisson的原理以及使用

系列博客目录 文章目录 系列博客目录怎么样才能够在简历上写熟悉redisson的应用以及原理1. 清晰描述技能与经验示例&#xff1a; 2. 列举具体应用场景示例项目经验&#xff1a; 3. 展示你对原理的理解示例&#xff1a; 4. 用简历中的关键词突出你的能力示例段落&#xff1a; 5.…

分布式任务调度xxl-job入门案例

XXL-JOB是一个分布式任务调度平台&#xff0c;简单来说就是可以在你指定的时间内调用某个功能&#xff0c;就例如购物某个商品的限时抢购从什么时候开始以及结束抢购类似于这样的。 下面是它的一个仓库地址 http://gitee.com/xuxueli0323/xxl-job 下载之后将项目导入进idea中&…