日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

单例模式源码分析(jdk+spring+mybatis)

發布時間:2024/4/13 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 单例模式源码分析(jdk+spring+mybatis) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
我們首先看一個簡單的,Runtime這個類在java.lang下的,我們看一下getRuntime()public static Runtime getRuntime() {return currentRuntime; }可以看到這里直接返回一個currentRuntimeprivate static Runtime currentRuntime = new Runtime();我們可以看到這個對象是static,并且在類加載的時候就已經創建出來了,屬于餓漢式,非常簡單,我們再看一個Desktop,awt的,只不過現在用JAVAD寫服務端比較多一點,但是這個也分領域,某些也用JAVA寫桌面程序非常多,打個比方,Eclipse就是用JAVA寫的,還是非常強大的,那我們看一下,我們看一下getDesktop這個方法public static synchronized Desktop getDesktop(){if (GraphicsEnvironment.isHeadless()) throw new HeadlessException();if (!Desktop.isDesktopSupported()) {throw new UnsupportedOperationException("Desktop API is not " +"supported on the current platform");}sun.awt.AppContext context = sun.awt.AppContext.getAppContext();Desktop desktop = (Desktop)context.get(Desktop.class);if (desktop == null) {desktop = new Desktop();context.put(Desktop.class, desktop);}return desktop; }這個方法關注的,synchronized同步方法,獲取桌面對象,同步方法,最后返回,那我們看一下這里面AppContext,這個是一個App的上下文,然后下邊做了各種判斷,判斷這個對象是否為空,如果是空的話就new一個,放進去,那我們來看一下這個對象context,這里面的put做了什么呢

首先這里有this.table,點開table看一下,它是一個HashMap類型

這些判斷先忽略,看重點,然后給這個map上了個鎖,下面就開始put了,向HashMap里面放值,那我們再退回來,public static synchronized Desktop getDesktop(){if (GraphicsEnvironment.isHeadless()) throw new HeadlessException();if (!Desktop.isDesktopSupported()) {throw new UnsupportedOperationException("Desktop API is not " +"supported on the current platform");}sun.awt.AppContext context = sun.awt.AppContext.getAppContext();Desktop desktop = (Desktop)context.get(Desktop.class);if (desktop == null) {desktop = new Desktop();context.put(Desktop.class, desktop);}return desktop; }這里面同步方法,sun.awt.AppContext context = sun.awt.AppContext.getAppContext();然后看一下這行,這個從上下文里面,去獲取這個類型的對象,然后下面又有空判斷,如果為空就往里面put,最后就返回,那這里講的就非常像我們之前講的容器單例,可以找到容器單例的一個影子,只不過這里加了各種同步的控制,包括put的時候,還有這個方法調用的時候,來保證這一塊是線程安全的,那講完這些我們再想一下,那Spring中的單例,和我們寫的這個單例還不太一樣,那Spring的單例呢,是基于容器的,打個比方,如果我寫一個主函數,或者一個應用,啟動了多個容器,那在每個容器中都能夠拿到這個單例對象,也就是說呢,Spring里面的單例模式和我們講的單例模式,不是一個,那Spring中的單例呢,是bean作用域中的一個,這個作用域在每個應用上下文中,僅創建一個,我們設置單例屬性的這個實例,那和我們的設計模式最大區別是什么呢,Spring將實例的數量,作用域在整個應用程序的上下文,而我們這個單例模式呢,而我們寫的這種單例模式,在JAVA應用程序中,是將這些實例的數量,限制在類加載器管理的整個空間里,所以剛剛也說了,Spring啟動容器的時候,每個容器即使是單例的,我都可以拿出來這個對象,那其實在Spring中,能找到一些單例的影子,你看這個類,AbstractFactoryBean,我們找一個方法,getObject方法

我們可以看一下這里面做了一些判斷,也就是說判斷這個對象如果是單例的,就return,如果不是單例的就直接創建instance,createInstance(),從這個名字就能夠看出來,然后看一下這里面的語法,一個三元,是否被初始化呢,如果已經被初始化了,直接返回,如果沒有被初始化,調用getEarlySingletonInstance(),獲取早期的單例對象,我們來看一下

如果單例對象是空的話,通過代理去獲取這個對象,然后進行強轉,把這個對象賦值上,然后對他進行返回,現在我們再看一個關于Mybatis當中,使用單例模式的一些解決方案,我們打開他,public class ErrorContext,錯誤的上下文,那首先看到的就是這個private static final ThreadLocal<ErrorContext> LOCAL = new ThreadLocal<ErrorContext>();首先我們看一下他的構造器private ErrorContext() { }他的構造器是私有的,然后看一下instancepublic static ErrorContext instance() { ErrorContext context = LOCAL.get(); if (context == null) {context = new ErrorContext();LOCAL.set(context); } return context; }這里就基于ThreadLocal來使用了,而這個ThreadLocal呢,又是一個私有的靜態的final的private static final ThreadLocal<ErrorContext> LOCAL = new ThreadLocal<ErrorContext>();然后我們先不說這個,if (context == null) 我們先看一下這里,如果這個上下文是空的話,就創建一個新的,創建完成之后,把它放到ThreadLocal里邊,如果這個線程下次來的話,肯定能夠get出來,然后就直接返回了,那Mybatis這里面的錯誤上下文,也就是說他保證了每個線程,各自的數據,不同的線程,每個線程自己的錯誤上下文,自己保存好,就像前面所講的,在線程隔離方面,是非常有益處的,基于ThreadLocal的這種單例模式,我們也找到了,只不過他不是并不是整個應用全局唯一,而是在線程里是唯一的,那單例模式的源碼呢,就分析到這里,希望在單例模式這里有所收獲,然后強調一點,如果問設計模式的話,喜歡問單例模式來挖掘深度,希望能把我們所講的這些單例模式,實現方案,優缺點,應用場景,及其在源碼中的一些使用,還有比如序列化的破壞,反射攻擊防御等等,這些都能理解透

?

總結

以上是生活随笔為你收集整理的单例模式源码分析(jdk+spring+mybatis)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。