文章目錄
獲取Subject
使用shiro獲取Subject的方法:
Subject subject = SecurityUtils.getSubject();
為什么,不管在哪通過SecurityUtils獲取的Subject 都是同一個呢?
而且Subject 里面還有用戶的信息.
猜想
首先,能在各個地方獲取Subject 只有一種辦法,就是通過ThreadLocal類來實現,那么SecurityUtils肯定維護了一個ThreadLocal.
源碼分析
首先看getSubject方法:
點到ThreadContext類:
說明是ThreadContext類維護了一個ThreadLocal;
ThreadContext是什么時候跟Subject綁定的呢?
我們發現有個方法:bind(Subject subject),
看誰掉了這個方法:
是SubjectCallable里面就開始綁定了,我們只要看是誰新建了SubjectCallable這個類就好了,發現在Subject里面執行execute的時候新建的,同時將subject也就是this傳進去了.
現在明了了,上篇講到subject創建詳解
里面有一張圖:
在創建了subject的時候就通過execute來執行過濾器鏈的方法,這時候將創建好的subject跟ThreadContext進行了綁定,所以我們在任何地方都可以通過SecurityUtils.getSubject()來獲取Subject.
猜想ThreadLocal是跟當前線程綁定的,如果我springmvc里面使用異步方法執行,在異步處理過程中能獲取到subject嗎?
是可以的,我們看ThreadContext里的的ThreadLocal具體實現就知道了:
主要功勞就是InheritableThreadLocal實現,這個實現大概做的事情就是如果父線程里面使用ThreadLocal了,然后在父線程里面又創建子線程,這是會將父線程的ThreadLocal拷貝到子線程里面,所以在異步線程里面是可以獲取到subject的.
這時候就會想如果是異步線程池呢,這一塊比較復雜,因為
InheritableThreadLocal實現的時候,如果是異步線程池,在一開始設置了ThreadLocal,他是有緩存的,詳情見:解決父子線程ThreadLocal中的緩存問題