欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java類(lèi)加載器ClassLoader詳解

 更新時(shí)間:2025年06月11日 10:45:03   作者:雷神樂(lè)樂(lè)  
這篇文章主要介紹了Java類(lèi)加載器ClassLoader,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

以下文章都是基于JDK1.8環(huán)境

一、類(lèi)的加載過(guò)程

JDK8引用的都是jar包

JDK11引用的都是model

我們編寫(xiě)的".java"文件需要通過(guò)javac編譯成".class"文件,而程序運(yùn)行時(shí),JVM會(huì)把".class"文件加載到內(nèi)存中,并創(chuàng)建對(duì)應(yīng)的class對(duì)象,這個(gè)過(guò)程被稱(chēng)為類(lèi)的加載。

簡(jiǎn)單來(lái)說(shuō):將class文件讀入內(nèi)存,并為之創(chuàng)建一個(gè)Class對(duì)象。

JVM運(yùn)行的是class文件,不單單是java語(yǔ)言,無(wú)論哪種語(yǔ)言編寫(xiě)的,只要文件是.class類(lèi)型的,就能夠在JVM上運(yùn)行。

學(xué)習(xí)類(lèi)加載器的目的:使用類(lèi)加載器可以讓我們得代碼7*24小時(shí),不間斷地運(yùn)行。即修改代碼后無(wú)需重啟就能生效,類(lèi)似于熱部署。

二、默認(rèn)的類(lèi)加載器

JVM通過(guò)類(lèi)加載器把“.class”文件加載到內(nèi)存中,默認(rèn)有 3 個(gè)類(lèi)加載器,分別是:

  • Bootstrap ClassLoader     啟動(dòng)類(lèi)加載器
  • ExtClassLoader               擴(kuò)展類(lèi)加載器
  • AppClassLoader              系統(tǒng)類(lèi)加載器(應(yīng)用類(lèi)加載器)

三個(gè)類(lèi)加載器各有不同的作用

(一)Bootstrap ClassLoader1.基本介紹

作用:加載JDK核心類(lèi)庫(kù)(String,Integer,Long,ArrayList等等)

方式:加載某個(gè)類(lèi)時(shí),在指定的路徑中(Jar包或文件夾)搜索這個(gè)類(lèi),如果搜到就加載,如果沒(méi)搜到,報(bào):ClassNotFoundException

搜索路徑:由 sun.boot.class.path 所指定的,比如:%JRE_HOME%\jre\lib下的rt.jar、resources.jar、charsets.jar等,也就是JDK核心類(lèi)庫(kù),其中 rt.jar 里面就存放著常用的 JAVA API

代碼演示:

public static void main(String[] args) {
    // 輸出String類(lèi)是被哪個(gè)類(lèi)加載器,加載到內(nèi)存中
    System.out.println(String.class.getClassLoader());
    // 獲取系統(tǒng)配置
    // bootstrap生效的時(shí)候會(huì)去sun.boot.class.path路徑下找對(duì)應(yīng)的類(lèi)
    String paths = System.getProperty("sun.boot.class.path");
    // windows下使用;分隔
    // linux使用:分隔
    String[] arr = paths.split(";");
    for (String s : arr) {
        System.out.println(s);
    }
}

返回結(jié)果:

為什么String.class.getClassLoader() 返回null?

原因是:Bootstrap ClassLoader是由C/C++編寫(xiě)的,是虛擬機(jī)的一部分,并不是JAVA中的類(lèi),所以無(wú)法在 Java 代碼中獲取它的引用,因此返回 null。

因此:如果一個(gè)類(lèi)(System.out.println(String.class.getClassLoader());)輸出為null,說(shuō)明該類(lèi)是被Bootstrap ClassLoader加載的。前提是基于JDK1.8環(huán)境。

Bootstrap ClassLoader加載String類(lèi)會(huì)去下面這些類(lèi)中尋找:

最后一行不是默認(rèn)路徑,是IDEA默認(rèn)添加的,紅框部分才是默認(rèn)加載路徑。

String類(lèi)在rt包下,按照上圖的順序依次向下找,在rt包中找到后,就不會(huì)繼續(xù)向下尋找了。

2.自定義路徑

可通過(guò) -Xbootclasspath 參數(shù)修改 Bootstrap ClassLoader 的搜索路徑

用法

含義

備注

-Xbootclasspath:路徑

指定的路徑會(huì)完全取代jdk核心的搜索路徑

堅(jiān)決不要用

-Xbootclasspath/a:路徑

指定的路徑會(huì)在jdk核心類(lèi)后搜索

可用

-Xbootclasspath/p:路徑

指定的路徑會(huì)在jdk核心類(lèi)前搜索

可用,不建議使用

注意:如果配置多個(gè)路徑,linux/unix下用“:”分割,windows下用“;”分割。

代碼演示:在 pom.xml 中添加 commons-io,同時(shí)也要把這個(gè)jar包放到D:\test 中

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.8.0</version>
</dependency>

添加JVM參數(shù),指定尋找的包路徑在jdk核心類(lèi)后搜索

-Xbootclasspath/a:D:\test\commons-io-2.8.0.jar

去這個(gè)包下尋找ByteOrderMark這個(gè)類(lèi)

修改代碼:

public static void main(String[] args) {
    // 輸出String類(lèi)是被哪個(gè)類(lèi)加載器,加載到內(nèi)存中
    // System.out.println(String.class.getClassLoader());
    System.out.println(ByteOrderMark.class.getClassLoader());
    // 獲取系統(tǒng)配置
    // bootstrap生效的時(shí)候會(huì)去sun.boot.class.path路徑下找對(duì)應(yīng)的類(lèi)
    String paths = System.getProperty("sun.boot.class.path");
    // windows下使用;分隔
    // linux使用:分隔
    String[] arr = paths.split(";");
    for (String s : arr) {
        System.out.println(s);
    }
}

運(yùn)行結(jié)果:

Bootstrap ClassLoader在JDK核心類(lèi)中找不到就會(huì)去指定的路徑下尋找。

(二)ExtClassLoader

1.基本使用

擴(kuò)展類(lèi)加載器,加載擴(kuò)展類(lèi)庫(kù),搜索路徑由-Djava.ext.dirs指定,比如:%JRE_HOME%\jre\lib\ext目錄下的jar包和class文件。即ExtClassLoader加載類(lèi)的時(shí)候會(huì)去下面的路徑尋找,找不到就會(huì)報(bào)錯(cuò)。

代碼演示:

public static void main(String[] args) {
    // 輸出String類(lèi)是被哪個(gè)類(lèi)加載器,加載到內(nèi)存中
    // System.out.println(String.class.getClassLoader());
    // System.out.println(ByteOrderMark.class.getClassLoader());
    System.out.println(DNSNameService.class.getClassLoader());
    // 獲取系統(tǒng)配置
    // 輸出 ExtClassLoader 掃描的路徑,注意:輸出的是文件夾
    String paths = System.getProperty("java.ext.dirs");
    // windows下使用;分隔
    // linux使用:分隔
    String[] arr = paths.split(";");
    for (String s : arr) {
        System.out.println(s);
    }
}

運(yùn)行結(jié)果:

sun.misc.Launcher$ExtClassLoader@383534aa

有$符號(hào)表示ExtClassLoader是Launcher這個(gè)類(lèi)的內(nèi)部類(lèi)。只要出現(xiàn)$就說(shuō)明后面是前面的內(nèi)部類(lèi)

搜索ExtClassLoader后,發(fā)現(xiàn)ExtClassLoader確實(shí)是個(gè)內(nèi)部類(lèi),并且還是靜態(tài)的。

2.配置指定路徑

-Djava.ext.dirs=D:\test

public static void main(String[] args) {
    // 輸出String類(lèi)是被哪個(gè)類(lèi)加載器,加載到內(nèi)存中
    // System.out.println(String.class.getClassLoader());
    System.out.println(ByteOrderMark.class.getClassLoader());
    // System.out.println(DNSNameService.class.getClassLoader());
    // 獲取系統(tǒng)配置
    // 輸出 ExtClassLoader 掃描的路徑,注意:輸出的是文件夾
    String paths = System.getProperty("java.ext.dirs");
    // windows下使用;分隔
    // linux使用:分隔
    String[] arr = paths.split(";");
    for (String s : arr) {
        System.out.println(s);
    }
}

代碼中表示,讓ExtClassLoader去D:\test文件夾下尋找ByteOrderMark這個(gè)類(lèi)。

運(yùn)行結(jié)果:

自定義路徑會(huì)把默認(rèn)路徑覆蓋掉,所以這種方法不建議使用,了解即可。

(三)AppClassLoader

AppClassLoader也叫SystemClassLoader(系統(tǒng)類(lèi)加載器),搜索路徑由java.class.path(CLASSPATH) 指定。加載項(xiàng)目中自己寫(xiě)的類(lèi) 第三方依賴包。

public static void main(String[] args) {
    // 輸出String類(lèi)是被哪個(gè)類(lèi)加載器,加載到內(nèi)存中
    // System.out.println(String.class.getClassLoader());
    // System.out.println(ByteOrderMark.class.getClassLoader());
    // System.out.println(DNSNameService.class.getClassLoader());
    System.out.println(Main.class.getClassLoader());
 
    // 獲取系統(tǒng)配置
    // 輸出 ExtClassLoader 掃描的路徑,注意:輸出的是文件夾
    String paths = System.getProperty("java.class.path");
    // windows下使用;分隔
    // linux使用:分隔
    String[] arr = paths.split(";");
    for (String s : arr) {
        System.out.println(s);
    }
}

運(yùn)行結(jié)果:

最下面的兩行是IDEA自帶的,無(wú)需理會(huì)

由此可以看出,IDEA在運(yùn)行java代碼時(shí),主動(dòng)給我們添加了很多路徑(JDK核心類(lèi)庫(kù)、擴(kuò)展類(lèi)庫(kù)、自己寫(xiě)的類(lèi)和第三方依賴包到classpath中),所以才會(huì)打印如此多的路徑。如下圖。

(四)類(lèi)加載器的初始化

1.源碼跟蹤

從上面的輸出可以發(fā)現(xiàn) ExtClassLoader、AppClassLoader都是 Java 對(duì)象,接下來(lái)看一下它們是如何創(chuàng)建的。

這兩個(gè)對(duì)象的生成都是在 Launcher 中完成的:Launcher類(lèi)是 java 程序的入口,在啟動(dòng) java 應(yīng)用的時(shí)候會(huì)首先創(chuàng)建Launcher類(lèi)的對(duì)象,創(chuàng)建Launcher類(lèi)的時(shí)候會(huì)創(chuàng)建ExtClassLoader、AppClassLoader。

Launcher類(lèi)太過(guò)于底層,所以無(wú)法打斷點(diǎn),構(gòu)造方法如下:

首先,創(chuàng)建 ExtClassLoader

ExtClassLoader對(duì)象創(chuàng)建成功后,將器傳入AppClassLoader中

點(diǎn)進(jìn)這個(gè)getAppClassLoader靜態(tài)方法:

super一直點(diǎn)到最上層,在這里,parent參數(shù)就是傳入的 ExtClassLoader。

由此可以看出:ExtClassLoader是AppClassLoader的父類(lèi)加載器。

2.ExtClassLoader和AppClassLoader的關(guān)系結(jié)論——父類(lèi)加載器

在 Java 中,AppClassLoader 和 ExtClassLoader 都是由 sun.misc.Launcher 類(lèi)創(chuàng)建的。盡管它們的名字中包含“ClassLoader”,但它們并不是通過(guò)繼承關(guān)系來(lái)定義父子關(guān)系的,而是通過(guò)設(shè)置父加載器的方式來(lái)實(shí)現(xiàn)的。這意味著 AppClassLoader 實(shí)際上是將 ExtClassLoader 作為其父類(lèi)加載器,而不是通過(guò)類(lèi)繼承的方式。

只有類(lèi)之間才會(huì)存在繼承關(guān)系,我們這里說(shuō)的是AppClassLoader 和 ExtClassLoader對(duì)象。

在 Java 類(lèi)加載器的上下文中,“父類(lèi)加載器”這個(gè)術(shù)語(yǔ)并不意味著類(lèi)加載器之間存在繼承關(guān)系(即它們不是通過(guò) extends 關(guān)鍵字定義的父子類(lèi)關(guān)系),而是指類(lèi)加載器之間的委派關(guān)系。具體來(lái)說(shuō),AppClassLoader 將 ExtClassLoader 作為其父類(lèi)加載器,指的是當(dāng) AppClassLoader 需要加載某個(gè)類(lèi)時(shí),它首先會(huì)請(qǐng)求 ExtClassLoader(它的父類(lèi)加載器)嘗試加載該類(lèi)。這種機(jī)制是基于“雙親委派模型”的。

因此,AppClassLoader的父類(lèi)是URLClassLoader;父類(lèi)加載器是ExtClassLoader。

通過(guò)debug可以看出來(lái),AppClassLoader的parent屬性是ExtClassLoader,ExtClassLoader的parent屬性是BootstrapClassLoader,前文提過(guò),顯示null,就說(shuō)明是BootstrapClassLoader。

三、雙親委派模式

(一)概念介紹

雙親委派模式是Java類(lèi)加載機(jī)制的核心原理,用于規(guī)范類(lèi)加載器之間的協(xié)作方式。其核心思想是:當(dāng)一個(gè)類(lèi)加載器收到類(lèi)加載請(qǐng)求時(shí),不會(huì)直接自己加載,而是將請(qǐng)求委派給父類(lèi)加載器,只有當(dāng)父類(lèi)加載器無(wú)法加載時(shí),才會(huì)由當(dāng)前類(lèi)加載器自己嘗試加載。

如果父加載器可以完成加載任務(wù),就成功返回;倘若父加載器無(wú)法完成此加載任務(wù),子加載器才會(huì)嘗試自己去加載。

(二)源碼解釋

加載一個(gè)類(lèi),一定先從 Launcher.AppClassLoader 的 loadClass 方法開(kāi)始。

protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
    // 1. 檢查是否已加載
    Class<?> c = findLoadedClass(name);
    if (c == null) {
        try {
            // 2. 委派給父類(lèi)加載器(遞歸向上)
            if (parent != null) {
                c = parent.loadClass(name, false);
            } else {
                c = findBootstrapClassOrNull(name);
            }
        } catch (ClassNotFoundException e) {
            // 父類(lèi)加載器未找到,繼續(xù)執(zhí)行
        }
        if (c == null) {
            // 3. 自己嘗試加載
            c = findClass(name);
        }
    }
    if (resolve) {
        resolveClass(c);
    }
    return c;
}

(三)雙親委派模式的核心優(yōu)勢(shì)

  • 安全性:確保核心類(lèi)(如java.lang.Object)只能由啟動(dòng)類(lèi)加載器加載,防止用戶自定義類(lèi)覆蓋JDK核心類(lèi),避免惡意代碼篡改。保證java核心api不會(huì)被隨意替換,專(zhuān)業(yè)說(shuō)法:沙箱安全機(jī)制。
  • 唯一性:同一名稱(chēng)的類(lèi)只會(huì)被加載一次(由首個(gè)能加載它的類(lèi)加載器完成),確保類(lèi)實(shí)例的兼容性。
  • 層級(jí)隔離:不同類(lèi)加載器加載的類(lèi)空間隔離,例如Tomcat的多個(gè)Web應(yīng)用可通過(guò)不同類(lèi)加載器隔離類(lèi)版本。

代碼示例:

自定義一個(gè)Integer類(lèi):

package java.lang;
 
public class Integer {
    public static void main(String[] args) {
        System.out.println("運(yùn)行自定義的Integer類(lèi)......");
    }
}

運(yùn)行結(jié)果:

原因是BootStrap ClassLoader已經(jīng)在核心類(lèi)庫(kù)中找到j(luò)ava.lang.Integer類(lèi)了,所以不會(huì)再加載自定義的java.lang.Integer類(lèi)了,這充分體現(xiàn)了JDK核心類(lèi)不會(huì)被覆蓋的優(yōu)勢(shì)。

四、動(dòng)態(tài)加載

(一)URLClassLoader

URLClassLoader是Java中用于從指定的URL(統(tǒng)一資源定位符)加載類(lèi)和資源的類(lèi)加載器,屬于java.lang.ClassLoader的子類(lèi),也是ExtClassLoader和AppClassLoader的父類(lèi)。它允許從網(wǎng)絡(luò)或本地文件系統(tǒng)中的目錄、JAR 文件等位置動(dòng)態(tài)加載類(lèi),廣泛應(yīng)用于插件化開(kāi)發(fā)、熱部署、動(dòng)態(tài)模塊加載等場(chǎng)景。

常用的構(gòu)造方法:

  • URLClassLoader(URL[] urls, ClassLoader parent):使用指定的父加載器創(chuàng)建對(duì)象,從指定的urls路徑來(lái)查詢、并加載類(lèi)。
  • URLClassLoader(URL[] urls):使用默認(rèn)的父加載器(AppClassLoader)創(chuàng)建一個(gè)ClassLoader對(duì)象,從指定的urls路徑來(lái)查詢、并加載類(lèi)。

(二)實(shí)戰(zhàn)

新建一個(gè)普通的java項(xiàng)目parse-excel-demo,并打成jar包。

在另一個(gè)項(xiàng)目classloader-demo中編寫(xiě)下面的代碼,即可使用上面的方法

public class RunDemo {
    public static void main(String[] args) throws Exception {
        File file = new File(
                "G:\\develop\\workspace\\four\\" +
                        "newSmProjects\\parse-excel-demo\\target\\" +
                        "parse-excel-demo-1.0-SNAPSHOT.jar");
        URL[] urls = {file.toURI().toURL()};
        URLClassLoader myUrlClassLoader = new URLClassLoader(urls);
 
        Class<?> parseExcel = myUrlClassLoader.loadClass("com.test.excel.ParseExcel");
        Object obj = parseExcel.newInstance();
        Method parse = parseExcel.getMethod("parse");
        parse.invoke(obj);
    }
}

運(yùn)行結(jié)果:

即使被引用的jar包內(nèi)容被修改,只要路徑正確,RunDemo所在的項(xiàng)目都不需要重啟就能運(yùn)行:

RunDemo運(yùn)行結(jié)果:

(三)依賴問(wèn)題

有些時(shí)候,parse-excel-demo中可能引用一些第三方庫(kù),比如:jackson-core-2.11.0.jar

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-core</artifactId>
  <version>2.11.0</version>
</dependency>

并在代碼中使用:

package com.test.excel;
 
import com.fasterxml.jackson.core.JsonFactory;
 
public class ParseExcel {
    public void parse() {
        System.out.println("開(kāi)始解析Excel......");
        JsonFactory jsonFactory = new JsonFactory();
        System.out.println("運(yùn)行其getFormatGeneratorFeatures方法:" +
                jsonFactory.getFormatGeneratorFeatures());
    }
}

修改后重新對(duì) parse 打包,然后運(yùn)行clasterloader-demo中的代碼,結(jié)果:

問(wèn)題分析:

myUrlClassLoader的父類(lèi)加載器是

場(chǎng)景

父類(lèi)加載器

原因

默認(rèn)構(gòu)造URLClassLoader(urls)

AppClassLoader

默認(rèn)使用系統(tǒng)類(lèi)加載器作為父類(lèi)加載器。

顯式指定父類(lèi)加載器

任意(如ExtClassLoader)

可通過(guò)構(gòu)造方法URLClassLoader(urls,parent)自定義。

繼承關(guān)系

URLClassLoader是父類(lèi)

AppClassLoader和ExtClassLoader是URLClassLoader的子類(lèi)。

根據(jù)雙親委派模式,myUrlClassLoader加載時(shí)parseExcel的時(shí)候會(huì)去加載JsonFactory,加載JsonFactory會(huì)交給父類(lèi)加載器AppClassLoader,AppClassLoader無(wú)法加載就會(huì)交給其父類(lèi)加載器ExtClassLoader,ExtClassLoader無(wú)法加載又交給自己的父類(lèi)加載器BootStrap ClassLoader,都找不到才會(huì)報(bào)錯(cuò)。

因此,當(dāng)我們開(kāi)發(fā)中碰到ClassNotFoundException的排錯(cuò)方法要考慮類(lèi)的加載過(guò)程。

解決方案:完善代碼,將JsonFactory所屬的包放在myUrlClassLoader的掃描路徑下:

public class RunDemo {
    public static void main(String[] args) throws Exception {
        File file = new File(
                "G:\\develop\\workspace\\four\\" +
                        "newSmProjects\\parse-excel-demo\\target\\" +
                        "parse-excel-demo-1.0-SNAPSHOT.jar");
        File file2 = new File(
                "D:\\apache-maven-3.8.1\\repository\\" +
                        "com\\fasterxml\\jackson\\core\\jackson-core\\2.11.0" +
                        "\\jackson-core-2.11.0.jar");
        URL[] urls = {file.toURI().toURL(), file2.toURI().toURL()};
        URLClassLoader myUrlClassLoader = new URLClassLoader(urls);
 
        Class<?> parseExcel = myUrlClassLoader.loadClass("com.test.excel.ParseExcel");
        Object obj = parseExcel.newInstance();
        Method parse = parseExcel.getMethod("parse");
        parse.invoke(obj);
    }
}

也可以將依賴放入classloader-demo中。AppClassLoader可以成功加載第三方依賴包。

(四)版本沖突問(wèn)題

我們降低classloader-demo中的依賴版本:

再次運(yùn)行會(huì)報(bào)錯(cuò):

即使將2.11.0版本放到搜索路徑中還是會(huì)報(bào)錯(cuò),因?yàn)锳ppClassLoader已經(jīng)加載完畢了,myUrlClassLoader就不會(huì)再加載了。

而項(xiàng)目中已有的依賴也不能更改,那么如何解決呢?

讓程序同時(shí)運(yùn)行兩個(gè)版本的jsonFactory即可。

public class RunDemo {
    public static void main(String[] args) throws Exception {
        File file = new File(
                "G:\\develop\\workspace\\four\\" +
                        "newSmProjects\\parse-excel-demo\\target\\" +
                        "parse-excel-demo-1.0-SNAPSHOT.jar");
        File file2 = new File(
                "D:\\apache-maven-3.8.1\\repository\\" +
                        "com\\fasterxml\\jackson\\core\\jackson-core\\2.11.0" +
                        "\\jackson-core-2.11.0.jar");
        URL[] urls = {file.toURI().toURL(),file2.toURI().toURL()};
        // 創(chuàng)建自定義類(lèi)加載器
        // 這時(shí)候myUrlClassLoader的parent是ExtClassLoader        
        URLClassLoader myUrlClassLoader = new URLClassLoader(urls,RunDemo.class.getClassLoader().getParent());
 
        Class<?> parseExcel = myUrlClassLoader.loadClass("com.test.excel.ParseExcel");
        Object obj = parseExcel.newInstance();
        Method parse = parseExcel.getMethod("parse");
        parse.invoke(obj);
    }
}

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • SpringAop實(shí)現(xiàn)原理及代理模式詳解

    SpringAop實(shí)現(xiàn)原理及代理模式詳解

    Spring的AOP就是通過(guò)動(dòng)態(tài)代理實(shí)現(xiàn)的,使用了兩個(gè)動(dòng)態(tài)代理,分別是JDK的動(dòng)態(tài)代理和CGLIB動(dòng)態(tài)代理,本文重點(diǎn)給大家介紹下SpringAop實(shí)現(xiàn)原理及代理模式,感興趣的朋友一起看看吧
    2022-04-04
  • Java SpringBoot 集成 Redis詳解

    Java SpringBoot 集成 Redis詳解

    Redis 是一個(gè)由 Salvatore Sanfilippo 寫(xiě)的 key-value 存儲(chǔ)系統(tǒng),是跨平臺(tái)的非關(guān)系型數(shù)據(jù)庫(kù)。Redis 是一個(gè)開(kāi)源的使用 ANSI C 語(yǔ)言編寫(xiě)、遵守 BSD 協(xié)議、支持網(wǎng)絡(luò)、可基于內(nèi)存、分布式、可選持久性的鍵值對(duì)(Key-Value)存儲(chǔ)數(shù)據(jù)庫(kù),并提供多種語(yǔ)言的 API
    2021-10-10
  • SpringMVC體系分層模式原理圖解

    SpringMVC體系分層模式原理圖解

    這篇文章主要介紹了SpringMVC體系分層模式原理圖解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-06-06
  • java編程實(shí)現(xiàn)求解八枚銀幣代碼分享

    java編程實(shí)現(xiàn)求解八枚銀幣代碼分享

    這篇文章主要介紹了java編程實(shí)現(xiàn)求解八枚銀幣代碼分享,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-11-11
  • springbooot整合dynamic?datasource數(shù)據(jù)庫(kù)密碼加密方式

    springbooot整合dynamic?datasource數(shù)據(jù)庫(kù)密碼加密方式

    這篇文章主要介紹了springbooot整合dynamic?datasource?數(shù)據(jù)庫(kù)密碼加密方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • 使用lombok@Data存在extends時(shí)需要注意的問(wèn)題

    使用lombok@Data存在extends時(shí)需要注意的問(wèn)題

    在Java編程中,正確實(shí)現(xiàn)equals方法是保證對(duì)象比較一致性的關(guān)鍵,使用instanceof檢查類(lèi)型可能導(dǎo)致違反對(duì)稱(chēng)性原則,即當(dāng)子類(lèi)和父類(lèi)都重寫(xiě)equals時(shí)可能出現(xiàn)a.equals(b)不等于b.equals(a)的情況,Lombok的@EqualsAndHashCode注解可以通過(guò)callSuper=true參數(shù)
    2024-10-10
  • Java中增強(qiáng)for循環(huán)在一維數(shù)組和二維數(shù)組中的使用方法

    Java中增強(qiáng)for循環(huán)在一維數(shù)組和二維數(shù)組中的使用方法

    下面小編就為大家?guī)?lái)一篇Java中增強(qiáng)for循環(huán)在一維數(shù)組和二維數(shù)組中的使用方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-10-10
  • JDBC中PreparedStatement詳解以及應(yīng)用場(chǎng)景實(shí)例介紹

    JDBC中PreparedStatement詳解以及應(yīng)用場(chǎng)景實(shí)例介紹

    PreparedStatement對(duì)象代表的是一個(gè)預(yù)編譯的SQL語(yǔ)句,用它提供的setter方法可以傳入查詢的變量,這篇文章主要給大家介紹了關(guān)于JDBC中PreparedStatement詳解以及應(yīng)用場(chǎng)景實(shí)例介紹的相關(guān)資料,需要的朋友可以參考下
    2024-02-02
  • httpclient ConnectionHolder連接池連接保持源碼解析

    httpclient ConnectionHolder連接池連接保持源碼解析

    這篇文章主要為大家介紹了httpclient ConnectionHolder連接池連接保持源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-11-11
  • springboot security自定義認(rèn)證過(guò)程

    springboot security自定義認(rèn)證過(guò)程

    這篇文章主要介紹了springboot security自定義認(rèn)證過(guò)程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-03-03

最新評(píng)論