主頁 > 後端開發 > Spring 的依賴注入(DI)

Spring 的依賴注入(DI)

2023-06-30 07:30:25 後端開發

前言

歡迎來到本篇文章,書接上回,本篇說說 Spring 中的依賴注入,包括注入的方式,寫法,該選擇哪個注入方式以及可能出現的回圈依賴問題等內容,

如果正在閱讀的朋友還不清楚什么是「依賴」,建議先看看我第一篇文章,通過 Employee 和 Department 簡單說了什么是所謂的依賴,

什么是依賴注入?

依賴注入是一個程序,舉個例子:

public class A {
    private B b;
    // 省略 getter 和 setter
    // 省略構造方法
}

現在 A 類 是依賴 B 類的,沒有 B,A 什么都不是,Spring IoC 容器創建好 B 的實體物件后并賦值給 A 物件中的 b 屬性(成員變數)的程序,就是所謂的「依賴注入」,

當然,這也是所謂的控制反轉了,物件 b 的創建不是我們手動 new 創建的,而是 Spring IoC 容器創建的,

使用 DI 原則,可以讓代碼更加簡潔,當物件提供其依賴項時,解耦也更加有效,依賴項 B 注入給 A 的實體物件,A 的實體物件是不會查找它的依賴項 B 的,也不知道依賴項 B 的位置,

依賴注入主要有兩種實作方式:基于構造方法的依賴注入基于 Setter 的依賴注入

基于構造方法的依賴注入

基于構造方法的 DI 是通過 Spring IoC 容器呼叫帶有許多引數的構造方法來完成的,每個引數表示一個依賴項,這與上一篇中呼叫具有特定引數的靜態工廠方法來構造 Bean 是幾乎等價的,

public class Vehicle {
    
    // Vehicle 依賴于 Producer 物件,或者說 Vehicle 持有一個 Producer 依賴項
    private final Producer producer;
    
    // 構造方法,讓 Spring IoC 容器能夠注入 Producer 物件給 Vehicle 物件
    public Vehicle(Producer producer) {
        this.producer = producer;
    }
}

注意,這個 Vehicle 類就只是一個普通的 Java Bean,或者說 POJO,沒什么特別之處,最普通不過的類了,沒有繼承或者實作 Spring 指定的任意類,

構造方法中引數的決議

Spring IoC 是通過構造方法引數的決議來匹配需要注入的依賴項,換句話說,決議實際上就是通過匹配引數的型別,來確定注入什么依賴項

如果構造方法的引數中沒有存在潛在的歧義,那么在 Bean 被實體化的時候,構造方法中引數的順序和實體化時進行賦值是一樣的,

package cn.god23bin.demo.model;

public class A {
    private B b;
    private C c;
    
    public A(B b, C c) {
        this.b = b;
        this.c = c;
    }
}

單獨寫這些類,是完成不了依賴注入的,這時候需要配置元資料了,讓它與 Java 類相結合,才能發揮 Spring IoC 的作用,

現在假設 B 和 C 是沒有任何繼承上的關聯,也沒有任何潛在的歧義,那么我們在配置元資料中的配置是正常的,需要使用到 <constructor-arg/> 標簽,該標簽只需有一個 ref 屬性,即參考(reference),指明 A 的構造方法的引數為 B 和 C,如下:

<beans>
	<bean id="a" >
		<constructor-arg ref="b"/>
		<constructor-arg ref="c"/>
	</bean>

	<bean id="b" />

	<bean id="c" />
</beans>

我們知道,B 和 C 是屬于參考型別,型別是確切的,所以直接使用 ref 屬性

如果是基本資料型別,那么賦值時,就可能會有歧義,Spring 不能確定這個值的型別,比如一個基本資料型別的值是 true這時候歧義就出現了,它是布爾型別還是字串型別呢?這就需要由我們來告訴 Spring 了,就需要使用 typevalue 屬性來指定

比如:

package cn.god23bin.demo.model;

public class D {
    private final int money;
    private final String power;
    
    public D(int money, String power) {
        this.money = money;
        this.power = power;
    }
}
<bean id="d" >
	<constructor-arg type="int" value="https://www.cnblogs.com/god23bin/p/25000000"/>
	<constructor-arg type="java.lang.String" value="https://www.cnblogs.com/god23bin/p/25"/>
</bean>

當然,除了使用 type 指定基本資料型別,還有兩個屬性可以解決歧義,分別是 indexname 屬性,

index 屬性:

使用 index 屬性指定構造方法引數的下標,下標是從 0 開始的,來解決引數型別出現歧義的情況,

<bean id="d" >
	<constructor-arg index="0" value="https://www.cnblogs.com/god23bin/p/25000000"/>
	<constructor-arg index="1" value="https://www.cnblogs.com/god23bin/p/25"/>
</bean>

name 屬性:

使用 name 屬性指定構造方法引數的名稱來解決歧義,

<bean id="d" >
	<constructor-arg name="money" value="https://www.cnblogs.com/god23bin/p/25000000"/>
	<constructor-arg name="power" value="https://www.cnblogs.com/god23bin/p/25"/>
</bean>

基于 Setter 的依賴注入

基于 Setter 的 DI,是在 Spring IoC 容器呼叫了 Bean 的無參構造方法或者無參的靜態工廠方法實體化了 Bean 之后,再來呼叫 Bean 的 Setter 方法來實作的,

下面這個依舊是普通的 Java Bean,當然你加上相關業務邏輯,就不是純粹的 Java Bean 了,不過 Spring 依舊能夠管理這種物件,

Vehicle:

public class Vehicle {
    
    // Vehicle 持有的 Producer 依賴項
    private Producer pro;
    
    // 同理
    private Author aut;
    
    // 同理
    private int money;
    
    // setter 方法,可以讓 Spring IoC 容器呼叫注入 Producer 物件
    public void setProducer(Producer pro) {
        this.pro = pro;
    }
    
    // 同理
    public void setAut(Author aut) {
        this.aut = aut;
    }
    
    // 同理
    public void setMoney(int money) {
        this.money = money
    }
    
    // 業務邏輯,有關 Producer 的...
}

對應的配置元資料:

<bean id="vehicle" >
    <!-- 使用 property 標簽的 ref 屬性注入參考型別的依賴項 -->
    <property name="pro" ref="producer"/>
    <!-- 使用內嵌 ref 標簽 注入 -->
    <property name="aut">
    	<ref bean="author"/>
    </property>
    <property name="money" value="https://www.cnblogs.com/god23bin/p/255"/>
</bean>

<bean id="producer" />
<bean id="author" />

Spring IoC 容器(ApplicationContext)支持基于構造方法的 DI 和基于 Setter 的 DI,也支持使用構造方法注入了一部分依賴項后,再使用 Setter 的方式注入其他的依賴項,

我們可以通過配置一個 BeanDefinitionPropertyEditor 來實作這些屬性的注入,但是,我們基本不會這樣用,而是使用 XML 的 Bean 定義,使用注解的 Bean 定義(比如 @Component@Controller 等),又或者使用 @Bean 這種基于 Java 配置類的方式(@Configuration)來定義,

實際上,這些最終都會轉成 BeanDefinition 物件的并被 Spring IoC 使用,

選擇哪個 DI 方式?

在代碼的撰寫中,選擇使用構造方法注入還是使用 Setter 注入呢?

官網上是這么說的:

Since you can mix constructor-based and setter-based DI, it is a good rule of thumb to use constructors for mandatory dependencies and setter methods or configuration methods for optional dependencies. Note that use of the @Autowired annotation on a setter method can be used to make the property be a required dependency; however, constructor injection with programmatic validation of arguments is preferable.

The Spring team generally advocates constructor injection, as it lets you implement application components as immutable objects and ensures that required dependencies are not null. Furthermore, constructor-injected components are always returned to the client (calling) code in a fully initialized state. As a side note, a large number of constructor arguments is a bad code smell, implying that the class likely has too many responsibilities and should be refactored to better address proper separation of concerns.

Setter injection should primarily only be used for optional dependencies that can be assigned reasonable default values within the class. Otherwise, not-null checks must be performed everywhere the code uses the dependency. One benefit of setter injection is that setter methods make objects of that class amenable to reconfiguration or re-injection later. Management through JMX MBeans is therefore a compelling use case for setter injection.

Use the DI style that makes the most sense for a particular class. Sometimes, when dealing with third-party classes for which you do not have the source, the choice is made for you. For example, if a third-party class does not expose any setter methods, then constructor injection may be the only available form of DI.

簡而言之,Spring 團隊是推薦用構造方法來完成 DI 的

  • 對于強依賴項,直接用基于構造方法的 DI,這種注入方式能夠保證注入的 Bean 物件不可變,并且確保需要的依賴不為空,此外,構造方法注入的依賴總是能夠在回傳客戶端(呼叫方)的時候保證完全初始化的狀態,

  • 對于可選的弱依賴項,使用基于 Setter 的 DI,當使用 @Autowired 注解,并將注解用到 Setter 方法上的話,那么這個 Setter 設定的屬性就變成強依賴了,

對于構造方法進行 DI ,其中:

  • 依賴不可變:其實說的就是 final 關鍵字,
  • 依賴不為空:省去了我們對注入的 Bean 的檢查,當要實體化 Bean 的時候,由于自己實作了有引數的構造方法,所以不會呼叫默認構造方法,那么就需要 Spring IoC 容器傳入所需要的引數給有參構造方法,所以就兩種情況,有該型別的引數傳入,那么 OK ;無該型別的引數,那么報錯,
  • 完全初始化的狀態:這個可以跟上面的依賴不為空結合起來,向構造方法傳參之前,要確保注入的內容不為空,那么肯定要呼叫依賴物件的構造方法完成實體化,而在 Java 類加載實體化的程序中,構造方法是最后一步才執行的,所以回傳來的實體化物件都是完全初始化之后的狀態,

依賴的處理程序

Spring IoC 容器按如下方式執行 Bean 的依賴處理(Dependency Resolution Process,個人認為把 Resolution 理解成處理,解決等意思比較好),

  • 根據配置元資料的內容,ApplicationContext 被創建和初始化,這個配置元資料是用來描述所有 Bean 的,它可以是 XML、Java 代碼或注解,
  • 對于每個 Bean 來說,它的依賴是以屬性、構造方法引數或靜態工廠方法的引數(如果你用它代替構造方法)的形式表達的,在 Spring IoC 創建 Bean 的時候,這些依賴會被提供給需要的 Bean,
  • 每個屬性或構造方法引數都是要設定的值的實際定義,或對容器中另一個 Bean 的參考,
  • 每個作為值的屬性或構造方法引數都會從其指定格式轉換為該屬性或構造方法引數的實際型別,默認情況下,Spring 可以將以字串格式提供的值轉換為所有內置型別,如 intlongStringboolean 等等,

當 Spring IoC 容器被創建時,Spring IoC 容器一開始就會校驗每個 Bean 的配置,在創建 Bean 之前,Bean 的屬性本身不會被設定,

而且當容器被創建時,那些具有單例作用域的 Bean 也默認會被創建,對于其他情況的 Bean,只有在被請求時才會創建,

一個 Bean 的創建是有可能導致一堆 Bean 被創建,這一堆的 Bean 被稱為 Bean 圖(a graph of beans),因為 Bean 與 Bean 之間可能存在相互依賴,如同社會中的人一樣,都有相關的聯系,所以形成 Bean 圖,

Bean 作用域在進行 Bean 定義的時候可以進行定義,使用 scope 屬性即可定義 Bean 的作用域,

回圈依賴

當你使用建構式注入的時候,某種情況下可能產生一個無法解決的回圈依賴問題,那什么是回圈依賴

舉個例子:

public class A {
    private B b;
    
    public A(B b) {
        this.b = b;
    }
}
public class B {
    private A a;
    
    public B(A a){
        this.a = a;
    }
}

如上所示,A 類通過構造方法注入需要 B 類的物件,而 B 類也通過構造方法注入 A 類的一個物件,這種情況就是所謂的回圈依賴,A 和 B 之間相互依賴,

A 和 B 之間的回圈依賴關系會迫使其中一個 Bean 在未完全初始化之前,被注入到另一個 Bean 中,

這時候,Spring IoC 容器會在運行時檢測到這種回圈的參考,并拋出一個 BeanCurrentlyInCreationException

有一種解決方案就是:修改 A 類或者 B 類的源代碼,使其通過 Setter 方式注入依賴項,

當然,一般情況下,我們可以完全相信 Spring,Spring 會在容器加載時檢測配置問題,如檢查參考不存在的 Bean 或回圈依賴等,它會盡量晚地設定 Bean 的屬性以及處理依賴的關系,

假設當你請求一個物件時,如果在創建該物件或其依賴關系時出現問題,已經正確加載的 Spring 容器就會產生例外,所以,這意味著我們需要提前發現這些問題,

默認情況下,ApplicationContext 會預先實體化單例 Bean,所以在創建 Spring IoC 容器時會花費一些時間和記憶體,但好處是可以在容器創建時發現配置問題,而不是在后續出現,

如果不存在回圈依賴關系,一個 Bean 在被注入到另一個 Bean 之前會被完全配置,這意味著當 A 依賴于 B 時,Spring IoC 容器會先完全配置好 B(包括實體化 Bean、設定依賴關系和呼叫相關的生命周期方法),再呼叫 A 的 Setter 方法,

依賴注入示例

下面寫下示例,快速回顧下上面的兩種注入方式,幫助大家更好理解在以 XML 作為配置元資料的情況下,使用基于構造方法的 DI 和基于 Setter 的 DI,

  1. 基于構造方法的 DI:
package cn.god23bin.demo.service;

import cn.god23bin.demo.repository.UserRepository;

public class UserService {
	
    // UserService 的依賴項 UserRepository
	private UserRepository userRepository;

    // 使用構造方法進行 DI,將 UserRepository 注入到 UserService
	public UserService(UserRepository userRepository) {
    	this.userRepository = userRepository;
	}
    
}
<bean id="userService" >
   <constructor-arg ref="userRepository" />
</bean>

<bean id="userRepository"  />
  1. 基于 Setter 的 DI:
package cn.god23bin.demo.service;

import cn.god23bin.demo.repository.UserRepository;

public class UserService {
    
	private UserRepository userRepository;

	public void setUserRepository(UserRepository userRepository) {
		this.userRepository = userRepository;
	}
    
}
<bean id="userService" >
   <property name="userRepository" ref="userRepository" />
</bean>

<bean id="userRepository"  />

總結

本文開頭舉了個例子講了什么是依賴注入,實際上就是一個程序,把一個 Bean 注入到另一個 Bean 中的程序,

這個程序,在 Spring 中有兩種方式來實作,一種是基于構造方法的 DI,另一種是基于 Setter 的DI,當然,網上講到的依賴注入,還有好幾種方式,目前對于我們來說,知道這兩種就 OK,

對于這兩種 DI,我們也說了如何選擇,具體看官網的說法,推薦的是基于構造方法的 DI,當然,具體問題具體分析,有時候是需要用到基于 Setter 的 DI 的,比如解決回圈依賴的時候,

接著也說了依賴的處理程序,簡單點就是 Spring 會先根據配置元資料去創建 ApplicationContext 這個作為 Spring IoC 容器,在容器創建時,會驗證 Bean 是否正確配置了,默認單例的 Bean 會先被創建等等等的處理,同時可能遇到回圈依賴的問題,一種解決方案就是將某一個 Bean 使用 Setter 的方式注入依賴項,

以上,便是本篇文章的內容了,下期咱們講講依賴注入的一些細節寫法,比如有的依賴項是集合,那么配置元資料中該如何寫這個集合,進而實作集合的依賴注入等等,

希望本篇有幫助到大家,有興趣的話可以關注我,關注這個系列!

最后的最后

希望各位螢屏前的靚仔靚女們給個三連!你輕輕地點了個贊,那將在我的心里世界增添一顆明亮而耀眼的星!

咱們下期再見!

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/556289.html

標籤:Java

上一篇:6 sleep與yield的比較

下一篇:返回列表

標籤雲
其他(161838) Python(38259) JavaScript(25516) Java(18284) C(15238) 區塊鏈(8273) C#(7972) AI(7469) 爪哇(7425) MySQL(7273) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5875) 数组(5741) R(5409) Linux(5347) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4609) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2438) ASP.NET(2404) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) .NET技术(1985) HtmlCss(1976) 功能(1967) Web開發(1951) C++(1942) python-3.x(1918) 弹簧靴(1913) xml(1889) PostgreSQL(1881) .NETCore(1863) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Spring 的依賴注入(DI)

    歡迎來到本篇文章,書接上回,本篇說說 Spring 中的依賴注入,包括注入的方式,寫法,該選擇哪個注入方式以及可能出現的回圈依賴問題等內容。

    如果正在閱讀的朋友還不清楚什么是「依賴」,建議先看看我第一篇文章,通過 Employee 和 Department 簡單說了什么是所謂的依賴。 ......

    uj5u.com 2023-06-30 07:30:25 more
  • 6 sleep與yield的比較

    # 6 sleep與yield的比較 ## sleep 1. 呼叫 sleep 會讓當前執行緒從 *Running* 進入 *Timed Waiting* 狀態(阻塞) 2. 其它執行緒可以使用 interrupt 方法打斷正在睡眠的執行緒,這時 sleep 方法會拋出 InterruptedExcept ......

    uj5u.com 2023-06-30 07:30:17 more
  • Java反射原始碼學習之旅

    在我剛開始了解反射這個Java特性的時候,幾乎看到的每一篇文章都會有“Java反射不能頻繁使用”、“反射影響性能”之類的話語,當時只是當一個結論記下了這些話,卻沒有深究過為什么,所以正好借此機會來探究一下Java反射的代碼。 ......

    uj5u.com 2023-06-30 07:30:13 more
  • 帶有 Spring Boot 后端的 Vue.js 前端

    1. 概述 在開始本教程中,先推薦1個SpringBoot+Vue前后端分離Java專案,本專案是一個大型互聯網金融專案,采用Spring Boot , Dubbo 微服務的架構,包括多個獨立的微服務,micr-common個公共服務,micr-web服務,micr-database資料庫服務,mi ......

    uj5u.com 2023-06-30 07:30:08 more
  • 【后端面經-Java】公平鎖和加鎖流程

    [TOC](【后端面經-Java】公平鎖和加鎖流程) ## 1. 公平鎖和非公平鎖 ### 1.1 基本概念 - 公平鎖:執行緒按照到來的先后順序,排隊等待使用資源。 - 非公平鎖:執行緒不一定按照先后順序使用資源,而是可能出現“插隊”的情況。 拿游樂場等待娛樂專案舉例,普通游客只能按照先后順序排隊等待 ......

    uj5u.com 2023-06-30 07:28:04 more
  • JSP

    # JSP ## 什么是JSP? Java Server pages:java服務器端頁面,和Servlet一樣,用于動態web技術 最大的特點: - 寫jsp就像在寫HTML - 區別: - HTML只能提供靜態資料, - JSP頁面可以嵌入java代碼,為用戶提供動態資料 ## JSP原理 瀏覽 ......

    uj5u.com 2023-06-30 07:27:47 more
  • Spring Boot 專案設計業務操作日志功能,寫得太好了!

    # 前言 很久以前都想寫這篇文章,一直沒有空,但直到現在我對當時的情景還有印象,之所以有印象是因為需求很簡單,業務操作日志的記錄與查詢的功能,但是具體實作真的很爛,具體的爛法會在反面示例里細說,領導以及客戶層面很認可,一系列迷之操作,讓我印象深刻。 # 需求描述與分析 客戶側提出需求很簡單:要對幾個 ......

    uj5u.com 2023-06-30 07:27:25 more
  • Java 面向物件

    ## 類和物件 ### 定義類 面向物件的程式設計程序中有兩個重要概念:類(class)和物件(object,也被稱為實體,instance),其中類是某一批物件的抽象,可以把類理解成某種概念;物件才是一個具體存在的物體 Java語言是面向物件的而程式設計語言,類和物件是面向物件的核心 Java語言 ......

    uj5u.com 2023-06-30 07:21:47 more
  • 【后端面經-Java】AQS詳解

    [TOC](【后端面經-Java】AQS詳解) ## 1. AQS是什么? AQS定義了一套多執行緒訪問共享資源的同步器框架,許多同步類實作都依賴于它,如常用的ReentrantLock。 簡單來說,**AQS定義了一套框架,來實作同步類**。 ## 2. AQS核心思想 ### 2.1 基本框架 A ......

    uj5u.com 2023-06-29 09:16:42 more
  • JavaCV人臉識別三部曲之二:訓練

    ### 歡迎訪問我的GitHub > 這里分類和匯總了欣宸的全部原創(含配套原始碼):[https://github.com/zq2599/blog_demos](https://github.com/zq2599/blog_demos) ### 本篇概覽 - 本文是《JavaCV人臉識別三部曲》的第 ......

    uj5u.com 2023-06-29 09:16:32 more