通过SecurityUtils获取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中的缓存问题

验证:

在这里插入图片描述

世界上所有的不公平都是由于当事人能力不足造成的.
原文地址:https://www.cnblogs.com/javayida/p/13346781.html