天天看點

【追尋源碼的世界】通過Shiro.ini檔案擷取SecurityManager的過程

故事的背景是:部落客正在研究shiro的原理及源碼。

本篇博文研究的代碼塊為:

// 建立 securityManager工廠,通過配置檔案ini建立
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:Shiro.ini");

SecurityManager securityManager = factory.getInstance();      

附上Shiro.ini檔案的内容

[users]
user1= 123, root, admin
user2 = 456, user

[roles]
root = *
admin = video:delete,video:add,video:update
user = video:find,video:buy      

好的,話不多說,直接進入正題

第一行代碼之源碼的世界:

Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:Shiro.ini");      

第一步:我們在使用new IniSecurityManagerFactory("classpath:Shiro.ini")時,會去調用IniSecurityManagerFactory中的new Ini().fromResourcePath(String path),想以此來擷取一個Ini執行個體。

第二步:在Ini.fromResourcePath()中,會調用Ini類的loadFromPath(String path)來擷取到一個ini執行個體,這個執行個體中會包含一個map,這個map的内容就是我們Shiro.ini檔案中[users]和[roles]中的資訊了。

第三步:在擷取到了ini執行個體之後,又回到了IniSecurityManagerFactory類中,先是調用自身的構造方法擷取一個factory執行個體,然後就去調用其父類IniFactorySupport的setIni(ini)方法,去初始化IniFactorySupport中的ini變量。

至此,我們的第一行代碼解析完畢。

第二行代碼之源碼的世界:

SecurityManager securityManager = factory.getInstance();      

第四步:通過調用factory.getInstance()方法,去調用AbstracFactory類的子類IniFactorySupport的createInstance()去擷取securityManager執行個體。

第五步:在IniFactorySupport類中,先通過resolveIni()擷取第三步初始化的ini執行個體,然後調用其子類IniSecurityManagerFactory的createInstance(Ini ini)去擷取securityManager

第六步:在IniSecurityManagerFactory的createInstance()方法中,會調用createSecurityManager(Ini ini)方法

第七步:在createSecurityManager(Ini ini)方法中,主要通過以下幾個步驟最終得到一個SecurityManager,并設定其realms

先是通過buildInstance()方法,根據ini得到一個map,map中會有我們Shiro.ini檔案的相關配置資訊。

然後調用getSecurityManager()方法擷取bean,此處擷取到的是DefaultSecurityManager的bean。

然後根據上面得到的map建立realms。具體源碼為:Collection<Realm> realms = getRealms(map);

然後調用applyRealmsToSecurityManager(realms, securityManager)方法。

在applyRealmsToSecurityManager()方法中,通過調用DefaultSecurityManager的setRealms(realms)方法,将realms設定到securityManager中,并傳回securityManager執行個體。

到此,第二行的代碼也解析完畢啦。

這也是部落客本次研究的心得,給大家分享一下~

後續會持續更新,帶來一些預設realm的生成的源碼世界探究 ^-^