最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

對Spring中bean線程安全的討論

 更新時間:2025年06月29日 13:51:21   作者:找不到、了  
這篇文章主要介紹了對Spring中bean線程安全的討論,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

Spring容器中的Bean是否線程安全,容器本身并沒有提供Bean的線程安全策略,因此Spring容器中的Bean本身不具備線程安全的特性,但是具體要結(jié)合具體的scope、靜態(tài)變量、常量、成員變量等多種屬性去研究。   

1、Bean狀態(tài)介紹

1.1、有狀態(tài)對象

有實(shí)例變量的對象,即每個用戶最初都會得到一個初始的bean,可以保存數(shù)據(jù),是非線程安全的。

每個用戶有自己特有的一個實(shí)例,在用戶的生存期內(nèi),bean保持了用戶的信息,即“有狀態(tài)”;一旦用戶滅亡(調(diào)用結(jié)束或?qū)嵗Y(jié)束),bean的生命期也告結(jié)束。

代碼示例:

@Service
public class Counter {
    private int count = 0;  // 有狀態(tài):保存實(shí)例變量

    public void increment() {
        count++;  // 非原子操作,線程不安全
    }

    public int getCount() {
        return count;
    }
}
  • 多個線程調(diào)用 increment() 時,count++操作可能因指令重排或并發(fā)寫入導(dǎo)致數(shù)據(jù)不一致。

1.2、無狀態(tài)對象

沒有實(shí)例變量的對象,不能保存數(shù)據(jù),是不變類,是線程安全的

  • bean一旦實(shí)例化就被加進(jìn)會話池中,各個用戶都可以共用。即使用戶已經(jīng)消亡,bean 的生命期也不一定結(jié)束,它可能依然存在于會話池中,供其他用戶調(diào)用。
  • 由于沒有特定的用戶,那么也就不能保持某一用戶的狀態(tài),所以叫無狀態(tài)bean。但無狀態(tài)會話bean 并非沒有狀態(tài),
  • 如果有自己的屬性(變量),那么這些變量就會受到所有調(diào)用它的用戶的影響。

代碼示例如下:

@Service
public class Calculator {
    // 無狀態(tài):不保存任何實(shí)例變量
    public int add(int a, int b) {
        return a + b;
    }
}
  • 多個線程調(diào)用add(1,2)時,結(jié)果不會互相影響。

兩者的區(qū)別和聯(lián)系:

2、Bean作用域

bean的生命周期如下所示:

實(shí)例化--->設(shè)置屬性--->初始化--->銷毀

Spring 的 bean 作用域(scope)類型:

1、singleton:單例,默認(rèn)作用域。

  • 優(yōu)點(diǎn): 節(jié)省內(nèi)存,因?yàn)橹淮嬖谝粋€實(shí)例。
  • 缺點(diǎn): 由于多個線程可能共享同一個實(shí)例,需要格外注意線程安全(非線程安全的狀態(tài)字段可能導(dǎo)致問題)

2、prototype:原型,每次創(chuàng)建一個新對象。

3、request:請求,每次Http請求創(chuàng)建一個新對象,適用于WebApplicationContext環(huán)境下。

4、session:會話,同一個會話共享一個實(shí)例,不同會話使用不用的實(shí)例。

5、global-session:全局會話,所有會話共享一個實(shí)例。

3、線程安全:

從單例與原型Bean分別進(jìn)行說明。

3.1、bean的分類

1、原型Bean

對于原型Bean,每次創(chuàng)建一個新對象,也就是線程之間并不存在Bean共享,自然是不會有線程安全的問題。

2、單例Bean

對于單例Bean,所有線程都共享一個單例實(shí)例Bean,因此是存在資源的競爭。

3.2、bean的安全

1、@Controller相關(guān)

可以這樣理解:

如果單例Bean,是一個無狀態(tài)Bean,在線程中的操作不會對Bean的成員執(zhí)行查詢以外的操作,那么這個單例Bean是線程安全的

比如Spring mvc 的 Controller、Service、Dao等,這些Bean大多是無狀態(tài)的,默認(rèn)情況下@Controller沒有加上@Scope,默認(rèn)Scope就是默認(rèn)值singleton,單例的 ,系統(tǒng)只會初始化一次 Controller 容器,只關(guān)注于方法本身。

但是,如果每次請求的都是同一個 Controller 容器里面的非線程安全的字段,那么就不是線程安全的。

代碼示例:

@RestController
public class TestController {
    //非線程安全的字段
    private int var = 0;
    @GetMapping(value = "/test_var")
    public String test() {
        System.out.println("普通變量var:" + (++var));
        return "普通變量var:" + var ;
    }
}

輸出:
普通變量var:1
普通變量var:2
普通變量var:3

修改了作用于改為:prototype

每個請求都單獨(dú)創(chuàng)建一個 Controller 容器,所以各個請求之間是線程安全的。

@RestController
@Scope(value = "prototype") // 加上@Scope注解,有2個取值:單例-singleton 多實(shí)例-prototype
public class TestController {
    private int var = 0;
    @GetMapping(value = "/test_var")
    public String test() {
        System.out.println("普通變量var:" + (++var));
        return "普通變量var:" + var ;
    }
}
輸出:
普通變量var:1
普通變量var:1
普通變量var:1

總結(jié)

1、@Controller/@Service 等容器中,默認(rèn)情況下,scope值是單例- singleton 的,是線程不安全的。

2、盡量不要在 @Controller/@Service 等容器中定義靜態(tài)變量,不論是單例( singleton )還是多實(shí)例( prototype )都是線程不安全的。

3、默認(rèn)注入的Bean對象,在不設(shè)置scope的時候也是線程不安全的。

4、一定要定義變量的話,用 ThreadLocal 來封裝,這個是線程安全的。

2、@prototype注解

@Scope 注解的 prototype 實(shí)例一定就是線程安全的嗎?

答案是否定的。上面已經(jīng)解釋過了,需要根據(jù)多方位去考量。

@RestController
@Scope(value = "prototype") // 加上@Scope注解,有2個取值:單例-singleton 多實(shí)例-prototype
public class TestController {
    private int var = 0;
    //只會初始化一次,因此也非線程安全的變量
    private static int staticVar = 0;
?
    @GetMapping(value = "/test_var")
    public String test() {
        System.out.println("普通變量var:" + (++var)+ "---靜態(tài)變量staticVar:" + (++staticVar));
        return "普通變量var:" + var + "靜態(tài)變量staticVar:" + staticVar;
    }
}

輸出:
普通變量var:1---靜態(tài)變量staticVar:1
普通變量var:1---靜態(tài)變量staticVar:2
普通變量var:1---靜態(tài)變量staticVar:3

總結(jié):線程安全在于怎樣去定義變量以及 Controller 的配置。

示例:

config里面自己定義的Bean: User

@Configuration
public class MyConfig {
    @Bean
    public User user(){
        return new User();
    }
}
@RestController
@Scope(value = "singleton") // prototype singleton
public class TestController {
?
    private int var = 0; // 定義一個普通變量
?
    private static int staticVar = 0; // 定義一個靜態(tài)變量
?
    @Value("${test-int}")
    private int testInt; // 從配置文件中讀取變量
?
    ThreadLocal<Integer> tl = new ThreadLocal<>(); // 用ThreadLocal來封裝變量
?
    @Autowired
    private User user; // 注入一個對象來封裝變量
?
    @GetMapping(value = "/test_var")
    public String test() {
        tl.set(1);
        System.out.println("先取一下user對象中的值:"+user.getAge()+"===再取一下hashCode:"+user.hashCode());
        user.setAge(1);
        System.out.println("普通變量var:" + (++var) + "===靜態(tài)變量staticVar:" + (++staticVar) + "===配置變量testInt:" + (++testInt)
                + "===ThreadLocal變量tl:" + tl.get()+"===注入變量user:" + user.getAge());
        return "普通變量var:" + var + ",靜態(tài)變量staticVar:" + staticVar + ",配置讀取變量testInt:" + testInt + ",ThreadLocal變量tl:"
                + tl.get() + "注入變量user:" + user.getAge();
    }
}

輸出:

先取一下user對象中的值:0===再取一下hashCode:241165852

普通變量var:1===靜態(tài)變量staticVar:1===配置變量testInt:1===ThreadLocal變量tl:1===注入變量user:1

先取一下user對象中的值:1===再取一下hashCode:241165852

普通變量var:2===靜態(tài)變量staticVar:2===配置變量testInt:2===ThreadLocal變量tl:1===注入變量user:1

先取一下user對象中的值:1===再取一下hashCode:241165852

普通變量var:3===靜態(tài)變量staticVar:3===配置變量testInt:3===ThreadLocal變量tl:1===注入變量user:1

在單例模式下 Controller 中只有用 ThreadLocal 封裝的變量是線程安全的??梢钥吹?次請求結(jié)果里面只有 ThreadLocal 變量值每次都是從 0+1=1 的,其他的幾個都是累加的,而 user 對象呢,默認(rèn)值是0,第二交取值的時候就已經(jīng)是1了,關(guān)鍵它的 hashCode 是一樣的,說明每次請求調(diào)用的都是同一個 user 對象。

TestController 上的 @Scope 注解的屬性改一下改成多實(shí)例的: @Scope(value = "prototype") ,其他都不變,再次請求,結(jié)果如下:

public class MyConfig {
    @Bean
    @Scope(value = "prototype")
    public User user(){
        return new User();
    }    
}
@RestController
@Scope(value = "prototype") // prototype singleton
public class TestController {
?
    private int var = 0; // 定義一個普通變量
?
    private static int staticVar = 0; // 定義一個靜態(tài)變量
?
    @Value("${test-int}")
    private int testInt; // 從配置文件中讀取變量
?
    ThreadLocal<Integer> tl = new ThreadLocal<>(); // 用ThreadLocal來封裝變量
?
    @Autowired
    private User user; // 注入一個對象來封裝變量
?
    @GetMapping(value = "/test_var")
    public String test() {
        tl.set(1);
        System.out.println("先取一下user對象中的值:"+user.getAge()+"===再取一下hashCode:"+user.hashCode());
        user.setAge(1);
        System.out.println("普通變量var:" + (++var) + "===靜態(tài)變量staticVar:" + (++staticVar) + "===配置變量testInt:" + (++testInt)
                + "===ThreadLocal變量tl:" + tl.get()+"===注入變量user:" + user.getAge());
        return "普通變量var:" + var + ",靜態(tài)變量staticVar:" + staticVar + ",配置讀取變量testInt:" + testInt + ",ThreadLocal變量tl:"
                + tl.get() + "注入變量user:" + user.getAge();
    }
}

先取一下user對象中的值:0===再取一下hashCode:1612967699
普通變量var:1===靜態(tài)變量staticVar:1===配置變量testInt:1===ThreadLocal變量tl:1===注入變量user:1

先取一下user對象中的值:0===再取一下hashCode:985418837
普通變量var:1===靜態(tài)變量staticVar:2===配置變量testInt:1===ThreadLocal變量tl:1===注入變量user:1

先取一下user對象中的值:0===再取一下hashCode:1958952789
普通變量var:1===靜態(tài)變量staticVar:3===配置變量testInt:1===ThreadLocal變量tl:1===注入變量user:1

3、靜態(tài)變量

靜態(tài)變量的生命周期由 JVM 管理,與 Spring 無關(guān)。所有實(shí)例(單例或原型)共享同一個靜態(tài)變量。

@Component
public class MyService {
    private static int count = 0; // 靜態(tài)變量

    public void increment() {
        count++; // 多線程環(huán)境下可能出問題
    }
}

在 Spring 中,無論是單例(Singleton)作用域還是原型(Prototype)作用域的 Bean,只要在類中定義了靜態(tài)變量(static 變量),都可能存在線程安全問題。

總結(jié):多實(shí)例模式下普通變量,取配置的變量還有 ThreadLocal 變量都是線程安全的,而靜態(tài)變量和 user 對象中的變量都是非線程安全的。

4、ThreadLocal

4.1、概念

ThreadLocal 類提供了線程局部變量,每個線程可以將一個值存在 ThreadLocal 對象中,其他線程無法訪問這些值。每個線程都有自己獨(dú)立的變量副本。

ThreadLocal 的初始值可通過 withInitial() 方法設(shè)置:

private static final ThreadLocal<String> requestId = 
    ThreadLocal.withInitial(() -> "default-id");

簡單的內(nèi)存模型:

+-----------------+          +------------------+
|    Thread A     |          |    Thread B      |
+-----------------+          +------------------+
| ThreadLocal     |          | ThreadLocal      |
| - value: 123    |          | - value: 456     |
+-----------------+          +------------------+

Thread A and Thread B can have different values in the same ThreadLocal.

不同線程直接保存了不同的值。

4.2、優(yōu)點(diǎn)

若單例 Bean 需要保存線程私有的狀態(tài)(如用戶請求上下文),多線程場景下,多個線程對這個單例Bean的成員變量并不存在資源的競爭,因?yàn)門hreadLocal為每個線程保存線程私有的數(shù)據(jù)。這是一種以空間換時間的方式。

4.3、原理

如下圖所示:

調(diào)用 ThreadLocal.set(value)方法時,它會將這個值與當(dāng)前線程關(guān)聯(lián),而該值被存儲在當(dāng)前線程的一個內(nèi)部數(shù)據(jù)結(jié)構(gòu)中。通過 ThreadLocal.get()方法,可以獲取當(dāng)前線程所關(guān)聯(lián)的值。

  • 核心機(jī)制:每個線程內(nèi)部維護(hù)一個 ThreadLocalMap(類似鍵值對存儲,以 ThreadLocal 對象為鍵,存儲線程私有的變量。
  • 數(shù)據(jù)隔離:線程通過自己的 ThreadLocalMap 訪問變量,不同線程之間的數(shù)據(jù)互不影響。
  • 內(nèi)存模型
Thread-1 → ThreadLocalMap → { ThreadLocalA → Value1, ThreadLocalB → Value2 }
Thread-2 → ThreadLocalMap → { ThreadLocalA → Value3, ThreadLocalB → Value4 }

4.4、注意

由于ThreadLocal里面維護(hù)了ThreadLocalMap類,如下圖所示:

而TheadLocalMap是由Entry[]組成組成,Entry[]維護(hù)了多個entry。如下所示:

一個entry由key(threadlocal)和value,Entry繼承了弱引用,關(guān)于弱引用可參考:對Java 資源管理和引用體系的介紹

如下圖所示:entry

如果使用不當(dāng),會引發(fā)oom問題,主要是由GC回收機(jī)制和內(nèi)存結(jié)構(gòu)兩者引起。

可參考:就ThreadLocal使用時OOM的討論

4.5、使用場景

  • 用戶會話信息: 在 web 應(yīng)用中維護(hù)用戶的會話信息,避免將狀態(tài)信息寫到全局上下文。
  • 數(shù)據(jù)庫連接: 在線程中維護(hù)數(shù)據(jù)源連接,避免不同線程之間共享資源引起的競爭。
  • 事務(wù)管理(如 Spring 的 TransactionSynchronizationManager)。

以下是一個簡單的 Spring Bean 示例,展示如何在 Spring 中使用 ThreadLocal 來存儲用戶會話信息。

1.定義一個 ThreadLocal Storage

import org.springframework.stereotype.Component;

@Component
public class UserContext {
    private static final ThreadLocal<String> userHolder = new ThreadLocal<>();

    public void setCurrentUser(String username) {
        userHolder.set(username);
    }

    public String getCurrentUser() {
        return userHolder.get();
    }

    //清理 ThreadLocal,防止內(nèi)存泄漏
    public void clear() {
        userHolder.remove(); // 清除當(dāng)前線程中的值
    }
}

2.使用 UserContext

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    @Autowired
    private UserContext userContext;

    public void login(String username) {
        userContext.setCurrentUser(username);
        System.out.println("User logged in: " + userContext.getCurrentUser());
    }

    public void logout() {
        System.out.println("User logged out: " + userContext.getCurrentUser());
        userContext.clear();
    }
}

3 示例測試類

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class UserServiceTest {

    @Autowired
    private UserService userService;

    @Test
    public void testThreadLocal() {
        userService.login("Alice");
        userService.logout();

        // Clear (will just have no output, but it demonstrates functionality)
        userService.login("Bob");
        userService.logout();
    }
}

4. 圖形展示

在多線程環(huán)境中的 ThreadLocal 可能如下圖所示:

+-------------------+
|      UserContext  |
|-------------------|
| ThreadLocal       |
| - userHolder      |
+-------------------+
     |         |
     |         |
     v         v
+------------+ +-------------+
| Thread A   | | Thread B    |
|------------| |------------ |
| - user: "Alice" | - user: "Bob" |
+------------+ +--------------+

在每個線程中,UserContext 提供了對 ThreadLocal 變量獨(dú)立的值,使得 Thread A 可以存儲與 Thread B 不同的用戶會話信息。

5、解決方案

根據(jù)以上介紹Spring Bean的線程安全問題,以下是各種常用的解決方案。

1、同步機(jī)制去處理

synchronized 關(guān)鍵字或者 ReentrantLock 可重入鎖。

示例:

synchronized介紹:

 import org.springframework.stereotype.Component;
 ?
 @Component
 public class OrderServiceBean {
 ?
     private int orderStatus;
 ?
     public synchronized void updateOrderStatus() {
         // 這里進(jìn)行更新訂單狀態(tài)的具體業(yè)務(wù)邏輯,比如根據(jù)某些條件修改orderStatus的值
         orderStatus++;
     }
 ?
     public int getOrderStatus() {
         return orderStatus;
     }
 }

ReentrantLock介紹:

 import org.springframework.stereotype.Component;
 import java.util.concurrent.locks.ReentrantLock;
 ?
 @Component
 public class OrderServiceBean {
 ?
     private int orderStatus;
     private ReentrantLock lock = new ReentrantLock();
 ?
     public void updateOrderStatus() {
         lock.lock();
         try {
             // 這里進(jìn)行更新訂單狀態(tài)的具體業(yè)務(wù)邏輯,比如根據(jù)某些條件修改orderStatus的值
             orderStatus++;
         } finally {
             lock.unlock();
         }
     }
 ?
     public int getOrderStatus() {
         return orderStatus;
     }
 }

2、Treadlocal對象(推薦)

3、采用不可變對象(Immutable Objects)

設(shè)置final對象或者成員變量屬性。

4、使用原子類(Atomic Classes)

 import org.springframework.stereotype.Component;
 import java.util.concurrent.atomic.AtomicInteger;
 ?
 @Component
 public class VisitCountBean {
 ?
     private AtomicInteger visitCount = new AtomicInteger(0);
 ?
     public void incrementVisitCount() {
         visitCount.incrementAndGet();
     }
 ?
     public int getVisitCount() {
         return visitCount.get();
     }
 }

在 Spring 中實(shí)現(xiàn)線程安全,尤其是涉及到多個線程共享狀態(tài)時,常常需要:

  • 選擇適當(dāng)?shù)?Bean 作用域。
  • 盡量減少或避免可變狀態(tài)。
  • 使用 ThreadLocal 來管理線程局部數(shù)據(jù)。
  • 使用 AOP 及 Spring 事務(wù)來處理業(yè)務(wù)邏輯。
  • 實(shí)現(xiàn)良好的設(shè)計(jì)模式以確保代碼的可維護(hù)性。

通過以上最佳實(shí)踐,可以有效地在 Spring 應(yīng)用中實(shí)現(xiàn)線程安全,確保系統(tǒng)的穩(wěn)定性和數(shù)據(jù)一致性。

總結(jié)

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

相關(guān)文章

  • Java 數(shù)組ArrayList常用語法詳解

    Java 數(shù)組ArrayList常用語法詳解

    這篇文章主要介紹了Java 數(shù)組ArrayList常用語法詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-09-09
  • 一篇文章帶你了解JAVA面對對象應(yīng)用

    一篇文章帶你了解JAVA面對對象應(yīng)用

    Java是一門面向?qū)ο蟮恼Z言。對象是Java程序中的基本實(shí)體。除了對象之外Java程序同樣處理基本數(shù)據(jù)。下面這篇文章主要給大家總結(jié)了關(guān)于Java中面向?qū)ο蟮闹R點(diǎn),需要的朋友可以參考借鑒,下面來一起看看吧
    2021-08-08
  • java調(diào)用未知類的指定方法簡單實(shí)例

    java調(diào)用未知類的指定方法簡單實(shí)例

    這篇文章介紹了java調(diào)用未知類的指定方法簡單實(shí)例,有需要的朋友可以參考一下
    2013-09-09
  • Java如何不解壓讀取.zip的文件內(nèi)容

    Java如何不解壓讀取.zip的文件內(nèi)容

    這篇文章主要給大家介紹了關(guān)于Java如何不解壓讀取.zip的文件內(nèi)容的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • JAVA入門教學(xué)之快速搭建基本的springboot(從spring boot到spring cloud)

    JAVA入門教學(xué)之快速搭建基本的springboot(從spring boot到spring cloud)

    本文主要入門者介紹怎么搭建一個基礎(chǔ)的springboot環(huán)境,本文通過圖文并茂的形式給大家介紹從spring boot到spring cloud的完美搭建過程,適用java入門教學(xué),需要的朋友可以參考下
    2021-02-02
  • JAVA項(xiàng)目swing轉(zhuǎn)javafx語法規(guī)則以及示例代碼

    JAVA項(xiàng)目swing轉(zhuǎn)javafx語法規(guī)則以及示例代碼

    這篇文章主要介紹了JAVA項(xiàng)目swing轉(zhuǎn)javafx語法規(guī)則以及示例代碼的相關(guān)資料,文中詳細(xì)講解了主類繼承、窗口創(chuàng)建、布局管理、控件替換、事件監(jiān)聽、線程安全、圖標(biāo)設(shè)置、顯示窗口等內(nèi)容,需要的朋友可以參考下
    2025-12-12
  • Java數(shù)據(jù)結(jié)構(gòu)之加權(quán)無向圖的設(shè)計(jì)實(shí)現(xiàn)

    Java數(shù)據(jù)結(jié)構(gòu)之加權(quán)無向圖的設(shè)計(jì)實(shí)現(xiàn)

    加權(quán)無向圖是一種為每條邊關(guān)聯(lián)一個權(quán)重值或是成本的圖模型。這種圖能夠自然地表示許多應(yīng)用。這篇文章主要介紹了加權(quán)無向圖的設(shè)計(jì)與實(shí)現(xiàn),感興趣的可以了解一下
    2022-11-11
  • SpringBoot整合Dozer映射框架流程詳解

    SpringBoot整合Dozer映射框架流程詳解

    dozer是用來兩個對象之間屬性轉(zhuǎn)換的工具,有了這個工具之后,我們將一個對象的所有屬性值轉(zhuǎn)給另一個對象時,就不需要再去寫重復(fù)的set和get方法了,下面介紹下SpringBoot中Dozer的使用,感興趣的朋友一起看看吧
    2022-07-07
  • Java查看和修改線程優(yōu)先級操作詳解

    Java查看和修改線程優(yōu)先級操作詳解

    JAVA中每個線程都有優(yōu)化級屬性,默認(rèn)情況下,新建的線程和創(chuàng)建該線程的線程優(yōu)先級是一樣的。本文將為大家詳解Java查看和修改線程優(yōu)先級操作的方法,需要的可以參考一下
    2022-08-08
  • Java面向?qū)ο箨P(guān)鍵字extends繼承的深入講解

    Java面向?qū)ο箨P(guān)鍵字extends繼承的深入講解

    繼承就是使用已定義的類作為父類,新建一個類作為子類使用extends關(guān)鍵字繼承這個類,這樣就實(shí)現(xiàn)了繼承關(guān)系,這篇文章主要給大家介紹了關(guān)于Java面向?qū)ο箨P(guān)鍵字extends繼承的相關(guān)資料,需要的朋友可以參考下
    2021-08-08

最新評論

广昌县| 泰宁县| 平度市| 东阳市| 石棉县| 绥芬河市| 会理县| 天长市| 铜梁县| 屏边| 崇左市| 柳林县| 久治县| 昌吉市| 玛曲县| 寻甸| 开平市| 沅陵县| 进贤县| 台安县| 社会| 宜宾县| 潍坊市| 西丰县| 四会市| 泰州市| 河曲县| 武安市| 从化市| 铜川市| 贵德县| 额敏县| 大田县| 济宁市| 巴林右旗| 伊春市| 威海市| 琼结县| 丽江市| 仁化县| 牡丹江市|