文章目录
- 获取Subject
- 猜想
- 源码分析
- ThreadContext是什么时候跟Subject绑定的呢?
- 猜想ThreadLocal是跟当前线程绑定的,如果我springmvc里面使用异步方法执行,在异步处理过程中能获取到subject吗?
- 验证:
获取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中的缓存问题
验证: