DelegatingFilterProxy的使用

在Spring集成第三方时,通常会提供以下方式的配置来作为第三方引入的入口:
<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> <!-- 默认是false -->
</init-param>
</filter>
<filter-mapping>
< filter-name>shiroFilter</filter-name>
< url-pattern>/*</url-pattern>
</filter-mapping>
从配置上来看,只是增加了一个filter,与引入的第三方框架没有什么关系。实际上DelegatingFilterProxy是org.springframework.web.filter中的一个特殊类,对于servlet filter进行代理,其好处在于可以通过spring容器来管理servlet filter对象及其生命周期。既然由spring容器进行管理,那和普通的bean就没有区别,也可以使用依赖注入机制、属性文件的操作等特性。

[b]那么DelegatingFilterProxy是如何实现filter的代理?[/b]
protected void initFilterBean() throws ServletException {
synchronized (this.delegateMonitor) {
if(this.delegate == null){
// If no target bean name specified, use filter name.
if (this.targetBeanName == null) {
this.targetBeanName = getFilterName();
}
// Fetch Spring root application context and initialize the delegate early,
// if possible. If the root application context will be started after this
// filter proxy, we'll have to resort to lazy initialization.
WebApplicationContext wac = findWebApplicationContext();
if (wac != null) {
this.delegate = initDelegate(wac);
}
}
}
}
从上述代码可以看出,如果没有提供初始化参数targetBeanName,就用filterName替代([color=red]必须与spring中定义的bean name对应[/color]),然后在spring IOC容器中获取该bean,下面看一下获取bean的代码initDelegate:
protected Filter initDelegate(WebApplicationContext wac) throws ServletException{
Filter delegate = wac.getBean(getTargetBeanName(), Filter.class);
if (isTargetFilterLifecycle()) {
delegate.init(getFilterConfig());
}
return delegate;
}
从容器中获取bean对象,通过判断isTargetFilterLifecycle决定是否调用init(),默认为false。从代码中Filter.class看出,该类必须实现Filter接口。在Shiro对应的bean为ShiroFilterFactoryBean,该类是一个工厂类,并没有实现Filter接口,表面上看与上面的原则相违背。实际情况ShiroFilterFactoryBean是一个Filter工厂,其有一个内部类SpringShiroFilter,继承于AbstractShiroFilter,实现了Filter接口。getObject()、getObjectType()两个方法返回的也都是SpringShiroFilter类型,因此getBean实际返回的是SpringShiroFilter。Shiro源码分析可以参考:[quote][url]http://blog.csdn.net/conansonic/article/details/49556129[/url][/quote]
获取Filter对象获取并执行init后,就需要关注doFilter,代码如下:
public void doFilter(ServletRequest request, ServletResponse response, 
FilterChain filterChain) throws ServletException, IOException {

// Lazily initialize the delegate if necessary.
Filter delegateToUse = null;
synchronized (this.delegateMonitor) {
if (this.delegate == null) {
WebApplicationContext wac = findWebApplicationContext();
if (wac == null) {
throw new IllegalStateException("No WebApplicationContext found: no ContextLoaderListener registered?");
}
this.delegate = initDelegate(wac);
}
delegateToUse = this.delegate;
}

// Let the delegate perform the actual doFilter operation.
invokeDelegate(delegateToUse, request, response, filterChain);
}
以上代码,需要重点关注invokeDelegate,Lazily initialize只有在init未调用delegate未初始化时执行。invokeDelegate代码:
protected void invokeDelegate(
Filter delegate, ServletRequest request, ServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
delegate.doFilter(request, response, filterChain);
}
delegate为从spring容器中获取到的Filter,执行了doFilter方法。从上述代码可以看出DelegatingFilterProxy就是一个代理模式的应用,把servlet容器的filter与spring容器中bean有效的结合,综合了两者的特性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值