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) 编辑 收藏 举报