概述
这两天在跑一个spring mvc + spring session项目时发现应用启动时报了上面的那个错误,当然,我认为这个错误在spring security中应该也很常见,一般报错:"No bean named 'springSecurityFilterChains' available"。
其实上面的错误都是由于DelegatingFilterProxy这个Filter引起的。下面我会简单介绍一下这个错误因为什么引起的,同时给出解决方案。
spring session出错原因:
我相信很多人的web.xml配置应该是这样的:
<filter>
<filter-name>delegatingFilterProxy</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>delegatingFilterProxy</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
上面的配置是错误的,tomcat启动时首先加载配置文件中Filter,看到我们注册了DelegatingFilterProxy(Filter实现类),调用了如下两个核心方法:
@Override
protected void initFilterBean() throws ServletException {
synchronized (this.delegateMonitor) {
if (this.delegate == null) {
// 如果没有在web.xml中配置<init-param> targetBeanName,这里该属性默认为filter名字,我们前面配置的delegatingFilterProxy
if (this.targetBeanName == null) {
this.targetBeanName = getFilterName();
}
// 这里开始初始化spring容器
WebApplicationContext wac = findWebApplicationContext();
if (wac != null) {
// 初始化DelegatingFilterProxy实际代理的Filter
this.delegate = initDelegate(wac);
}
}
}
}
protected Filter initDelegate(WebApplicationContext wac) throws ServletException {
// 这里根据我们定义的filterName从spring容器中找bean,也就是找delegatingFilterProxy,但是我们没定义,所以会报bean异常
Filter delegate = wac.getBean(getTargetBeanName(), Filter.class);
if (isTargetFilterLifecycle()) {
delegate.init(getFilterConfig());
}
return delegate;
}
出错的原因在上面注释中阐述的很明白了,下面说解决办法。
spring session出错解决办法:
将上面web.xml中配置改为如下:
<filter>
<filter-name>delegatingFilterProxy</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>targetBeanName</param-name>
<param-value>springSessionRepositoryFilter</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>delegatingFilterProxy</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
spring文档中解释的很清楚,DelegatingFilterProxy就是一个过滤器代理,因为spring容器没有办法管理java ee容器中的实例,所以它通过将代理Filter定义在Java EE容器中,然后将通过该代理Filter的所有请求委托给spring容器中Filter,这就是DelegatingFilterProxy的本质作用。前面由于我们没有定义targetBean,spring默认取当前filter-name作为委托Filter,但是由于spring容器中并未定义DelegatingFilterProxy这个bean,所以报bean创建异常。因为spring session说白了就是做session共享,核心Filter为SpringSessionRepositoryFilter,这个类spring session已经默认配置在了SpringHttpSessionConfiguration中了,spring容器启动时就注册进了,所以调用getBean当然没问题,它也就是我们DelegatingFilterProxy最终要委托的对象。
spring security中出错原因:
有同学用过spring security可能会想到,在spring security中并没有像上面那样定义呀!spring security定义如下:
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
首先说明一下,上面配置是正确的,回到上面问题,这里DelegationFilterProxy并没有定义targetBean初始化阐述啊,为什么又可以呢?因为前面有一段代码是这样:
// 这里根据我们定义的filterName从spring容器中找bean,也就是找springSecurityFilterChain,但是我们没定义,spring security仍不会报错
Filter delegate = wac.getBean(getTargetBeanName(), Filter.class);
因为在webApplicationContext调用getBean过程中,会对beanName进行显式转换,AbstractBeanFactory中调用代码片段如下:
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
// 显式转换beanName
final String beanName = transformedBeanName(name);
...
}
因为有些bean可能定义了一些别名,spring也会根据别名找到正确的bean。答案也就在这里,spring security确实给DelegatingFilterProxy设置了别名,还是在xml文件解析过程中做的。代码段见下:HttpSecurityBeanDefinitionParser#registerFilterChainProxyIfNecessary
static void registerFilterChainProxyIfNecessary(ParserContext pc, Object source) {
// ...省略前面代码
pc.registerBeanComponent(new BeanComponentDefinition(fcpBean,
BeanIds.FILTER_CHAIN_PROXY));
// spring将springSecurityFilterChain注册别名org.springframework.security.filterChainProxy
pc.getRegistry().registerAlias(BeanIds.FILTER_CHAIN_PROXY,
BeanIds.SPRING_SECURITY_FILTER_CHAIN);
}
又由于spring容器初始化时已经进行了org.springframework.security.filterChainProxy这个bean的初始化,初始化的实例就是FilterChainProxy实例,它也是spring security核心过滤器链。所以在DelegatingFilterProxy中调用getBean("springSecurityFilterChain", Filter.class)能正常返回而不会报bean创建异常。
模拟spring security `No bean named 'springSecurityFilterChains' available`错误:
看过前面解释的同学应该已经知道如何模拟出现该错误了吧,因为spring注册别名时已经将filterName -> beanName定义死了,也就是我只认识springSecurityFilterChain这个<filter-name>,如果我把<filter-name>随便改一下,spring均会报找到不bean异常。
最后
以上就是爱笑小笼包为你收集整理的No bean named 'delegatingFilterProxy' available的全部内容,希望文章能够帮你解决No bean named 'delegatingFilterProxy' available所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复