Shiro的Subject创建的内部流程

我们在使用shiro进行编程时,使用的subject.login()等方法,但是查看org.apache.shiro.subject.Subject之后,你会发现Subject其实不是一个java class,而是interface,它里面的login()只是方法的声明,没有函数体,那么我们调用的Subject.login()方法最终由什么类去执行呢?因此我开始去了解shiro的subject的生成过程。

查看SubjectUtils个getSubject方法,如下:

从当前线程中获取Subject有没有?没有创建一个,通过Subject自己的Build设计模式,创建一个Subject,此时我们跟进Subject里面去看看。public interface Subject,Subject是个接口,Builder是一个内部静态类。

进入Subject中查看Build的buildSubject()方法,如下:

Subject内部结构图可以看到Builder中和管家绑定有关系:

最终,是SecurityManager实现了subject的创建工作。

但在Builder中的securityManager的类型是其实也只是一个interface SecurityManager,

如果跟进去看源码就会是:

createSubject仅仅只是一个接口声明。那么到底是哪个实现了SecurityManager接口的具体类去完成创建Subject的工作呢?那就要看Subject中的SecurityManager具体是获得哪个类型的实例。

查看Build的构造函数,如下:

如果是用空参数的Build()的构造方法,那么跟进SecurityUtils.getSecurityManager()去查看源码,如下:

那么最终的SecurityManager实例是什么,就要看你的shiro.ini里配置的是什么SecurityManager了(如果你自己有实现继承并实现属于自己的SecurityManager的话),如果没有自己另外定义,那么就是Shiro默认的DefaultSecurityManager类。

SecurityManager的继承结构非常的复杂,里面的处理流程非常的多,最后的实现是在DefaultSecurityManager。管家的继承类图如下:

最后的一个管理者实现了创造subject的方法。查看DefaultSecurityManager. createSubject(SubjectContext subjectContext)的源码,如下:

继续跟进DefaultSecurityManager的doCreateSubject()方法,源码如下:

查看DefaultSecurityManager的getSubjectFactory方法的源码,如下:

在DefaultSecurityManager的构造方法中,查看subjectFactory的具体类型,如下:

可以发现subjectFactory是DefaultSubjectFactory的实例。继续回到DefaultSecurityManager的doCreateSubject()方法查看DefaultSubjectFactory的createSubject()方法,如下:

而DelegatingSubject的构造方法源码如下:

到此,Subject已经被构造出来,其类型为DelegatingSubject,其中Delegate是委托的意思。

那么既然已经清楚Subject的构造流程那就来查看一下Subject.login方法的最终将由DelegatingSubject.login()执行。

有脾气的猫

QQ:1813574898

2019年2月10日

发布于 2019-02-10 15:39