簡單的回顧一下,web.xml配置中的Spring DelegatingFilterProxy 的這個Filter是如何找到WebApplicationcontext 配置(Spring.xml配置文件)中的ShiroFilterFactoryBean。web
web.xml配置:spring
<filter> <filter-name>securityFilter</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>
其實際是經過上面web.xml文件中的<filter-name>securityFilter</filter-name>,securityFilter去找到spring-context.xml配置文件中類型爲Filter,id爲securityFilter的Bean。apache
spring-context.xml配置文件:app
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"> <!-- 此處省略部分配置--> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <!-- 此處省略部分配置--> <property name="securityManager" ref="securityManager" /> <property name="unauthorizedUrl" value="/" /> <property name="filters"> <map> <entry key="formAuthc" value-ref="formAuthc" /> </map> </property> <property name="filterChainDefinitions"> <value> /static/** = anon /login = formAuthc /logout = logout </value> </property> </bean> </beans>
詳解的源碼分析可見http://my.oschina.net/u/1421030/blog/729706函數
前一節說到Spring的DelegatingFilterProxy是經過在Spring的配置文件中找到類型爲Filter且id與web.xml文件其filter-name一致的Bean來發現ShiroFilterFactoryBean的。 但咱們會發現ShiroFilterFactoryBean好像沒有實現Filter接口,是否是有什麼問題呢??源碼分析
ShiroFilterFactoryBean 聲明代碼:this
public class ShiroFilterFactoryBean implements FactoryBean, BeanPostProcessor...
其實ShiroFilterFactoryBean 實現了FactoryBean接口正式在這裏有咱們想要的。 ApplicationContext的對待FactoryBean類型的Bean,經過配置文件的中Bean的id獲得的實際上是FactoryBean#getObject方法對應類型的Bean詳細可見http://my.oschina.net/u/1421030/blog/729908。 如今來看看ShiroFilterFactoryBean 的getObject方法的具體實現吧。url
ShiroFilterFactoryBean #getObject代碼:.net
public Object getObject() throws Exception { if (instance == null) { instance = createInstance(); } return instance; }
再看看debug
ShiroFilterFactoryBean #createInstance代碼:
protected AbstractShiroFilter createInstance() throws Exception { logdebug("Creating Shiro Filter instance."); SecurityManager securityManager = getSecurityManager(); //省略部分代碼 //建立FilterChain管理器,會將Shiro默認的Filter加入進來,同時將配置文件中的Filter加進來 FilterChainManager manager = createFilterChainManager(); PathMatchingFilterChainResolver chainResolver = new PathMatchingFilterChainResolver(); chainResolver.setFilterChainManager(manager); return new SpringShiroFilter((WebSecurityManager) securityManager, chainResolver); }
能夠看到createInstance方法返回的是一個AbstractShiroFilter 類對象,而該類的父類實際實現了Filter接口。 再來看看createInstance方法中最重要的createFilterChainManager
ShiroFilterFactoryBean #createFilterChainManager代碼:
protected FilterChainManager createFilterChainManager() { /*建立默認的FilterChainManager,建立時會將anon, authc, authcBasic等Filter加入*/ DefaultFilterChainManager manager = new DefaultFilterChainManager(); Map<String, Filter> defaultFilters = manager.getFilters(); //apply global settings if necessary: for (Filter filter : defaultFilters.values()) { applyGlobalPropertiesIfNecessary(filter); } //獲得Spring配置文件中設置給ShiroFilterFactoryBean 的Filter Map<String, Filter> filters = getFilters(); /*省略部分代碼,此處將Spring設置給ShiroFilterFactoryBean 的Filter 加入DefaultFilterChainManager */ /*獲得配置文件中ShiroFilterFactoryBean 對應的filterChainDefinitions屬性設置的鍵值對 最終能根據vaule找到其對應的其實類Filter的全名與對應的FilterConfig信息 */ Map<String, String> chains = getFilterChainDefinitionMap(); if (!CollectionUtils.isEmpty(chains)) { for (Map.Entry<String, String> entry : chains.entrySet()) { String url = entry.getKey(); String chainDefinition = entry.getValue(); manager.createChain(url, chainDefinition); } } return manager; }
先看看 DefaultFilterChainManager manager = new DefaultFilterChainManager()
DefaultFilterChainManager構造函數代碼
public DefaultFilterChainManager() { this.filters = new LinkedHashMap<String, Filter>(); this.filterChains = new LinkedHashMap<String, NamedFilterList>(); //加入Shiro中默認的Filter addDefaultFilters(false); }
DefaultFilterChainManager#addDefaultFilters代碼
protected void addDefaultFilters(boolean init) { for (DefaultFilter defaultFilter : DefaultFilter.values()) { addFilter(defaultFilter.name(), defaultFilter.newInstance(), init, false); } }
DefaultFilter代碼
public enum DefaultFilter { anon(AnonymousFilter.class), authc(FormAuthenticationFilter.class), authcBasic(BasicHttpAuthenticationFilter.class), logout(LogoutFilter.class), //省略部分代碼 }
到這裏終於看到了爲何咱們可在spring-context.xml中的ShiroFilterFactoryBean定義中使用anon, authc,authcBasic等去設置filterChainDefinitions啦。 spring-context.xml配置文件:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"> <!-- 此處省略部分配置--> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <!-- 此處省略部分配置--> <property name="securityManager" ref="securityManager" /> <property name="unauthorizedUrl" value="/" /> <property name="filters"> <map> <entry key="formAuthc" value-ref="formAuthc" /> </map> </property> <property name="filterChainDefinitions"> <value> /static/** = anon /login = formAuthc /logout = logout </value> </property> </bean> </beans>
下面一些過程後面的文章分析。