shiro的启动过程-入口分析

我们知道,在使用shiro的时候,需要在web.xml中配置一个DelegatingFilterProxy,这个过滤器就是shiro的入口。然后在applicationContext.xml注册ShiroFilterFactoryBean这个bean。需要注意的是过滤器中的filter-name要跟ShiroFilterFactoryBean的Id一样。原理就是,shiro使用了委托机制,DelegatingFilterProxy这个过滤器是spring的,它不具备shiro的功能,因此去spring容器中寻找id为shiroFilter的bean去替自己干活。(具体怎么委托的,后面再讲)

    <filter>
        <filter-name>shiroFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        <init-param>
            <param-name>targetFilterLifecycle</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>shiroFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="securityManager" ref="securityManager" />
        <property name="loginUrl" value="/system/login" />
        <property name="successUrl" value="/aa" />
        <property name="unauthorizedUrl" value="/system/unauthorized" />
        <property name="filterChainDefinitions">
            <value>
                /js/** = anon
                /css/** = anon
                /images/** = anon
                /sys/** = anon
                /login/ = anon
            </value>
        </property>
    </bean>

细心的人,可能就发现问题了。DelegatingFilterProxy是一个filter,它具备过滤器的功能,然而ShiroFilterFactoryBean只是一个普通的bean,它只实现了FactoryBean,BeanPostProcessor这两个接口,按道理来,它并不具备拦截器的功能。那它是怎么完成DelegatingFilterProxy的委托任务呢?

  原因就是:ShiroFilterFactoryBean实现了FactoryBean接口。FactoryBean是Spring容器提供的一种可以扩展容器对象实例化逻辑的接口。提供了这三个方法。

 第一个方法返回实例化的bean,第二个方法返回实例化bean的类型,第三个方法定义是否单例。

接着看看ShiroFilterFactoryBean是怎么实现这3个方法的。

 看到返回一个SpringShiroFilter()的实例。

 返回SpringShiroFilter的类型。

继续看,SpringShiroFilter其实是ShiroFilterFactoryBean的一个内部类,而SpringShiroFilter最终也实现了Filter,也就具有了过滤器的功能。

 至此,应该就明白了。DelegatingFilterProxy实际上就是委托ShiroFilterFactoryBean的内部类SpringShiroFilter来完成自己的功能。

再思考问题:为什么shiro要这么设计。

我们知道filter是tomcat创建的,它的创建要早于spring bean的创建。但是shiro真正执行功能的filter的创建又依赖spring创建的其他bean。这样就导致依赖的bean为null。因此就采用了这种委托机制。

web.xml中targetFilterLifecycle这个属性的作用:

  如果不设置,默认是false。真正执行功能的是SpringShiroFilter这个类。因为这个类是又spring创建的,应该由spring来管理生命周期。但是它又是一个filter,默认是由tomcat来管理生命周期的。如果targetFilterLifecycle设置成true的话,filter在调用init()和destroy()方法时,就不起作用。

 

posted on 2020-07-17 15:55  ajax取个名字真难  阅读(433)  评论(0编辑  收藏  举报

导航