主頁 > 後端開發 > 死磕Spring之AOP篇 - Spring AOP常見面試題

死磕Spring之AOP篇 - Spring AOP常見面試題

2021-04-15 07:19:20 後端開發

該系列文章是本人在學習 Spring 的程序中總結下來的,里面涉及到相關原始碼,可能對讀者不太友好,請結合我的原始碼注釋 Spring 原始碼分析 GitHub 地址 進行閱讀,

Spring 版本:5.1.14.RELEASE

在開始閱讀 Spring AOP 原始碼之前,需要對 Spring IoC 有一定的了解,可查看我的 《死磕Spring之IoC篇 - 文章導讀》 這一系列文章

該系列其他文章請查看:《死磕 Spring 之 AOP 篇 - 文章導讀》

目錄
  • 什么是 AOP?
  • 為什么要引入 AOP?
  • 簡述 AOP 的使用場景?
  • 簡述 AOP 中幾個比較重要的概念
  • 你知道哪幾種 AOP 框架?
  • 什么是 AOP 代理?
  • 講講 JDK 動態代理?
  • 講講 CGLIB 動態代理?
  • JDK 動態代理和 CGLIB 動態代理有什么不同?
  • Spring AOP 和 AspectJ 有什么關聯?
  • Spring AOP 中有哪些 Advice 型別?
  • Spring AOP 中 Advisor 介面是什么?
  • 簡述 Spring AOP 自動代理的實作
  • 請解釋 Spring @EnableAspectJAutoProxy 的原理?
  • Spring Configuration Class CGLIB 提升與 AOP 類代理關系?
  • Sping AOP 應用到哪些設計模式?
  • Spring AOP 在 Spring Framework 內部有哪些應用?

什么是 AOP?

官方檔案:

AspectJ:Aspect-oriented programming is a way of modularizing crosscutting concerns much like object-oriented programming is a way of modularizing common concerns.

Spring:Aspect-oriented Programming (AOP) complements Object-oriented Programming (OOP) by providing another way of thinking about program structure. The key unit of modularity in OOP is the class, whereas in AOP the unit of modularity is the aspect. Aspects enable the modularization of concerns (such as transaction management) that cut across multiple types and objects. (Such concerns are often termed “crosscutting” concerns in AOP literature.)

AOP(Aspect-oriented Programming)面向切面編程,是一種開發理念,是 OOP 面向物件編程的補充,我們知道,Java 就是一門面向物件編程的語言,在 OOP 中最小的單元就是“Class 物件”,但是在 AOP 中最小的單元是“切面”,一個“切面”可以包含很多種型別和物件,對它們進行模塊化管理,例如事務管理,

為什么要引入 AOP?

Java OOP 存在哪些局限性?

  • 靜態化語言:類結構一旦定義,不容易被修改
  • 侵入性擴展:通過繼承或組合組織新的類結構

通過 AOP 我們可以把一些非業務邏輯的代碼(比如安全檢查、監控等代碼)從業務中抽取出來,以非入侵的方式與原方法進行協同,這樣可以使得原方法更專注于業務邏輯,代碼介面會更加清晰,便于維護,

簡述 AOP 的使用場景?

日志場景

  • 診斷背景關系,如:log4j 或 logback 中的 _x0008_MDC
  • 輔助資訊,如:方法執行時間

統計場景

  • 方法呼叫次數
  • 執行例外次數
  • 資料抽樣
  • 數值累加

安防場景

  • 熔斷,如:Netflix Hystrix
  • 限流和降級:如:Alibaba Sentinel
  • 認證和授權,如:Spring Security
  • 監控,如:JMX

性能場景

  • 快取,如 Spring Cache
  • 超時控制

可以說在我們的日常開發環境中都是離不開 AOP 的,

簡述 AOP 中幾個比較重要的概念

在 AOP 中有以下幾個概念:

  • AspectJ:切面,只是一個概念,沒有具體的介面或類與之對應,是 Join point,Advice 和 Pointcut 的一個統稱,

  • Join point:連接點,指程式執行程序中的一個點,例如方法呼叫、例外處理等,在 Spring AOP 中,僅支持方法級別的連接點,

  • Advice:通知,即我們定義的一個切面中的橫切邏輯,有“around”,“before”和“after”三種型別,在很多的 AOP 實作框架中,Advice 通常作為一個攔截器,也可以包含許多個攔截器作為一條鏈路圍繞著 Join point 進行處理,

  • Pointcut:切點,用于匹配連接點,一個 AspectJ 中包含哪些 Join point 需要由 Pointcut 進行篩選,

  • Introduction:引介,讓一個切面可以宣告被通知的物件實作任何他們沒有真正實作的額外的介面,例如可以讓一個代理物件代理兩個目標類,

  • Weaving:織入,在有了連接點、切點、通知以及切面,如何將它們應用到程式中呢?沒錯,就是織入,在切點的引導下,將通知邏輯插入到目標方法上,使得我們的通知邏輯在方法呼叫時得以執行,

  • AOP proxy:AOP 代理,指在 AOP 實作框架中實作切面協議的物件,在 Spring AOP 中有兩種代理,分別是 JDK 動態代理和 CGLIB 動態代理,

  • Target object:目標物件,就是被代理的物件,

你知道哪幾種 AOP 框架?

主流 AOP 框架:

  • AspectJ:完整的 AOP 實作框架
  • Spring AOP:非完整的 AOP 實作框架

Spring AOP 是基于 JDK 動態代理和 Cglib 提升實作的,兩種代理方式都屬于運行時的一個方式,所以它沒有編譯時的一個處理,那么因此 Spring 是通過 Java 代碼實作的,AspectJ 自己有一個編譯器,在編譯時期可以修改 .class 檔案,在運行時也會進行處理,

Spring AOP 有別于其他大多數 AOP 實作框架,目的不是提供最完整的 AOP 實作(盡管 Spring AOP 相當強大);相反,其目的是在 AOP 實作和 Spring IoC 之間提供緊密的集成,以提供企業級核心特性,

Spring AOP 從未打算與 AspectJ 競爭以提供全面的 AOP 解決方案,我們認為 Spring AOP 等基于代理實作的框架和 AspectJ 等成熟的框架都是有價值的,并且它們是互補的,而不是競爭關系,Spring 將 Spring AOP 和 IoC 與 AspectJ 無縫集成,以實作 AOP 的所有功能都可以在一個 Spring 應用中,這種集成不會影響 Spring AOP API 或 AOP Alliance API,保持向后兼容,

什么是 AOP 代理?

代理模式是一種結構性設計模式,通過代理類為其他物件提供一種代理以控制對這個物件的訪問,AOP 代理是 AOP 框架中 AOP 的實作,主要分為靜態代理和動態代理,如下:

  • 靜態代理:代理類需要實作被代理類所實作的介面,同時持有被代理類的參考,新增處理邏輯,進行攔截處理,不過方法還是由被代理類的參考所執行,靜態代理通常需要由開發人員在編譯階段就定義好,不易于維護,
    • 常用 OOP 繼承和組合相結合
    • AspectJ,在編輯階段會織入 Java 位元組碼,且在運行期間會進行增強,
  • 動態代理:不會修改位元組碼,而是在 JVM 記憶體中根據目標物件新生成一個 Class 物件,這個物件包含了被代理物件的全部方法,并且在其中進行了增強,
    • JDK 動態代理
    • 位元組碼提升,例如 CGLIB

講講 JDK 動態代理?

基于介面代理,通過反射機制生成一個實作代理介面的類,在呼叫具體方法時會呼叫 InvocationHandler 來處理,

需要借助 JDK 的 java.lang.reflect.Proxy 來創建代理物件,呼叫 Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) 方法創建一個代理物件,方法的三個入參分別是:

  • ClassLoader loader:用于加載代理物件的 Class 類加載器
  • Class<?>[] interfaces:代理物件需要實作的介面
  • InvocationHandler h:代理物件的處理器

新生成的代理物件的 Class 物件會繼承 Proxy,且實作所有的入參 interfaces 中的介面,在實作的方法中實際是呼叫入參 InvocationHandlerinvoke(..) 方法,

為什么 JDK 動態代理只能基于介面代理,不能基于類代理?

因為 JDK 動態代理生成的代理物件需要繼承 Proxy 這個類,在 Java 中類只能是單繼承關系,無法再繼承一個代理類,所以只能基于介面代理,

為什么 InvocationHandler 不直接宣告到這個代理物件里面,而是放入繼承的 Proxy 父類中?

我覺得代理類既然是 JDK 動態生成的,那么 JDK 就需要識別出哪些類是生成的代理類,哪些是非代理類,或者說 JDK 需要對代理類做統一的處理,這時如果沒有一個統一的類 Proxy 來進行參考根本無法處理,這只是筆者的想法,具體為什么這么做不知道有小伙伴知道不 ~

講講 CGLIB 動態代理?

JDK 動態代理的目標物件必須是一個介面,在我們日常生活中,無法避免開發人員不寫介面直接寫類,或者根本不需要介面,直接用類進行表達,這個時候我們就需要通過一些位元組碼提升的手段,來幫助做這個事情,在運行時,非編譯時,來創建一個新的 Class 物件,這種方式稱之為位元組碼提升,在 Spring 內部有兩個位元組碼提升的框架,ASM(過于底層,直接操作位元組碼)和 CGLIB(相對于前者更加簡便),

CGLIB 動態代理則是基于類代理(位元組碼提升),通過 ASM(Java 位元組碼的操作和分析框架)將被代理類的 class 檔案加載進來,修改其位元組碼生成一個子類,

需要借助于 CGLIB 的 org.springframework.cglib.proxy.Enhancer 類來創建代理物件,設定以下幾個屬性:

  • Class<?> superClass:被代理的類
  • Callback callback:回呼介面

新生成的代理物件的 Class 物件會繼承 superClass 被代理的類,在重寫的方法中會呼叫 callback 回呼介面(方法攔截器)進行處理,

如果你想設定一個 Callback[] 陣列去處理不同的方法,那么需要設定一個 CallbackFilter 篩選器,用于選擇具體的方法使用陣列中的哪個 Callback 去處理

JDK 動態代理和 CGLIB 動態代理有什么不同?

兩者都是在 JVM 運行時期新創建一個 Class 物件,實體化一個代理物件,對目標類(或介面)進行代理,JDK 動態代理只能基于介面進行代理,生成的代理類實作了這些介面;而 CGLIB 動態代理則是基于類進行代理的,生成的代理類繼承目標類,但是不能代理被 final 修飾的類,也不能重寫 final 或者 private 修飾的方法,

CGLIB 動態代理比 JDK 動態代理復雜許多,性能也相對比較差,

Spring AOP 和 AspectJ 有什么關聯?

Spring AOP 和 AspectJ 都是 AOP 的實作框架,AspectJ 是 AOP 的完整實作,Spring AOP 則是部分實作,AspectJ 有一個很好的編程模型,包含了注解的方式,也包含了特殊語法,Spring 認為 AspectJ 的實作在 AOP 體系里面是完整的,不需要在做自己的一些實作,

Spring AOP 整合 AspectJ 注解與 Spring IoC 容器,比 AspectJ 的使用更加簡單,也支持 API 和 XML 的方式進行使用,不過 Spring AOP 僅支持方法級別的 Pointcut 攔截,

為什么 Spring AOP 底層沒有使用 AspectJ 動態代理創建代理物件?

我覺得是因為 AspectJ 的特殊語法對于 Spring 或者 Java 開發人員來說不是很友好,使用起來可能有點困難,Spring 也選擇整合 AspectJ 的注解,使用起來非常方便,

Spring AOP 中有哪些 Advice 型別?

  • Around Advice,圍繞型通知器,需要主動去觸發目標方法的執行,這樣可以在觸發的前后進行相關相關邏輯處理
  • Before Advice,前置通知器,在目標方法執行前會被呼叫
  • After Advice,后置通知器
    • AfterReturning,在目標方法執行后被呼叫(方法執行程序中出現例外不會被呼叫)
    • After,在目標方法執行后被呼叫(執行程序出現例外也會被呼叫)
    • AfterThrowing,執行程序中拋出例外后會被呼叫(如果例外型別匹配)

執行順序(Spring 5.2.7 之前的版本):Around “前處理” > Before > 方法執行 > Around “后處理” > After > AfterReturning|AfterThrowing

執行順序(Spring 5.2.7 開始):Around “前處理” > Before > 方法執行 > AfterReturning|AfterThrowing > After > Around “后處理”

如下(在后續文章會進行分析,Spring 5.1.14):

Spring AOP 中 Advisor 介面是什么?

Advisor 是 Advice 的一個容器介面,與 Advice 是一對一的關系,它的子介面 PointcutAdvisor 是 Pointcut 和 Advice 的容器介面,將 Pointcut 過濾 Joinpoint 的能力和 Advice 進行整合,這樣一來就將兩者進行關聯起來了,

Pointcut 提供 ClassFilter 和 MethedMatcher,分別支持篩選類和方法,通過 PointcutAdvisor 和 Advice 進行整合,可以說是形成了一個“切面”,

簡述 Spring AOP 自動代理的實作

在我們有了 Join point(連接點)、Pointcut(切點)、Advice(通知)以及 AspectJ(切面)后,我們應該如何將他們“織入”我們的應用呢?在 Sping AOP 中提供了自動代理的實作,底層借助 JDK 動態代理和 CGLIB 動態代理創建物件,

回顧 Spring IoC 中 Bean 的加載程序,在整個程序中,Bean 的實體化前和初始化后等生命周期階段都提供了擴展點,會呼叫相應的 BeanPostProcessor 處理器對 Bean 進行處理,當我們開啟了 AspectJ 自動代理(例如通過 @EnableAspectJAutoProxy 注解),則會往 IoC 容器中注冊一個 AbstractAutoProxyCreator 自動代理物件,該物件實作了幾種 BeanPostProcessor,例如在每個 Bean 初始化后會被呼叫,決議出當前 Spring 背景關系中所有的 Advisor(會快取),如果這個 Bean 需要進行代理,則會通過 JDK 動態代理或者 CGLIB 動態代理創建一個代理物件并回傳,所以得到的這個 Bean 實際上是一個代理物件,這樣一來,開發人員只需要配置好 AspectJ 相關資訊,Spring 則會進行自動代理,和 Spring IoC 完美地整合在一起,

參考:《死磕Spring之IoC篇 - Bean 的創建程序》

請解釋 Spring @EnableAspectJAutoProxy 的原理?

使用了 @EnableAspectJAutoProxy 注解則會開啟 Spring AOP 自動代理,該注解上面有一個 @Import(AspectJAutoProxyRegistrar.class) 注解,AspectJAutoProxyRegistrar 實作了 ImportBeanDefinitionRegistrar 這個介面,在實作的方法中會注冊一個 AnnotationAwareAspectJAutoProxyCreator 自動代理物件(如果沒有注冊的話),且將其優先級設定為最高,同時決議 @EnableAspectJAutoProxy 注解的配置并進行設定,這個自動代理物件是一個 BeanPostProcessor 處理器,在 Spring 加載一個 Bean 的程序中,如果它需要被代理,那么會創建一個代理物件(JDK 動態代理或者 CGLIB 動態代理),

除了注解的方式,也可以通過 <aop:aspectj-autoproxy /> 標簽開啟 Spring AOP 自動代理,原理和注解相同,同樣是注冊一個自動代理物件,

@Import 注解的原理參考:《死磕Spring之IoC篇 - @Bean 等注解的實作原理》

XML 自定義標簽的原理參考:《死磕Spring之IoC篇 - 決議自定義標簽(XML 檔案)》

Spring Configuration Class CGLIB 提升與 AOP 類代理關系?

在 Spring 底層 IoC 容器初始化后,會通過 BeanDefinitionRegistryPostProcessor 對其進行后置處理,其中會有一個 ConfigurationClassPostProcessor 處理器會對 @Configuration 標注的 BeanDefinition 進行處理,進行 CGLIB 提升,這樣一來對于后續的 Spring AOP 作業就非常簡單了,因為這個 Bean 天然就是一個 CGLIB 代理,

在 Spring 5.2 開始 @Configuration 注解中新增了一個 proxyBeanMethods 屬性(默認為 true),支持顯示的配置是否進行 CGLIB 提升,畢竟進行 CGLIB 提升在啟動程序會有一定的性能損耗,且創建的代理物件會占有一定的記憶體,通過該配置進行關閉,可以減少不必要的麻煩,對 Java 云原生有一定的提升,

@Configuration 注解的 Bean 進行 CGLIB 提升后有什么作用呢?

舉個例子,大多數情況下,@Configuration Class 會通過 @Bean 注解為 Bean 定義,比如 @Bean User user() { return new User(); },那這樣是不是每次主動呼叫這個方法都會回傳一個新的 User 物件呢?

不是的,@Configuration Class 在得到 CGLIB 提升后,會設定一個攔截器專門對 @Bean 方法進行攔截處理,通過依賴查找的方式從 IoC 容器中獲取 Bean 物件,如果是單例 Bean,那么每次都是回傳同一個物件,所以當主動呼叫這個方法時獲取到的都是同一個 User 物件,

參考:《死磕Spring之IoC篇 - @Bean 等注解的實作原理》

Sping AOP 應用到哪些設計模式?

如下:

  • 創建型模式:抽象工廠模式、工廠方法模式、構建器模式、單例模式、原型模式
  • 結構型模式:配接器模式、組合模式、裝飾器模式、享元模式、代理模式
  • 行為型模式:模板方法模式、責任鏈模式、觀察者模式、策略模式、命令模式、狀態模式

關于每種設計模式,以及在 Spring AOP 中的應用在后續文章會進行簡單的介紹,

Spring AOP 在 Spring Framework 內部有哪些應用?

Spring 事件、Spring 事務、Spring 資料、Spring 快取抽象、Spring 本地調度、Spring 整合、Spring 遠程呼叫

在后續文章進行分析,

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

標籤:Java

上一篇:【gin-vue-admin】初始化資料庫失敗

下一篇:Java基礎回顧-多執行緒

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(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
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more