【异常】:No Bean Named ‘springSecurityFilterChain’ is Defined


问题描述

项目启动时控制台抛异常说找不到“springSecurityFilterChain”的bean。

org.springframework.beans.factory.NoSuchBeanDefinitionException: 
No bean named 'springSecurityFilterChain' is defined

问题分析

Web 组件加载顺序:Listener→Filter→Servlet
Spring IOC 容器:ContextLoaderListener 创建
SpringMVC IOC 容器:DispatcherServlet 创建
springSecurityFilterChain:从IOC 容器中找到对应的bean
ContextLoaderListener 初始化后,springSecurityFilterChain 就在ContextLoaderListener
创建的IOC 容器中查找所需要的bean,但是我们没有在ContextLoaderListener 的IOC 容
器中扫描SpringSecurity 的配置类,所以springSecurityFilterChain 对应的bean 找不到。

问题解决

方案一

将ContextLoaderListener 取消,原本由ContextLoaderListener 读取的Spring 配置文
件交给DispatcherServlet 负责读取

<!-- 配置ContextLoaderListener 来加载Spring 配置文件-->
<!-- needed for ContextLoaderListener -->
<!-- <context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-main-*.xml</param-value>
</context-param> -->
<!-- Bootstraps the root web application context before servlet initialization -->
<!-- <listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener> -->
<!-- 配置DispatcherServlet 来加载SpringMVC 配置文件-->
<!-- The front controller of this Spring Web application, responsible for
handling all application requests -->
<servlet>
<servlet-name>springDispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-web-mvc.xml,classpath:spring-persist-*.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Map all requests to the DispatcherServlet for handling -->
<servlet-mapping>
<servlet-name>springDispatcherServlet</servlet-name>
<!-- <url-pattern>/</url-pattern> -->
<url-pattern>*.html</url-pattern>
<url-pattern>*.json</url-pattern>
</servlet-mapping>

方案二:改源码

创建一个与:org.springframework.web.filter.DelegatingFilterProxy 同包同名的类
由于加载类机制会优先加载我们创建的类

 @Override
    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);
                }*/
            }
        }
    }


 @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

        // Lazily initialize the delegate if necessary.
        Filter delegateToUse = this.delegate;
        if (delegateToUse == null) {
            synchronized (this.delegateMonitor) {
                delegateToUse = this.delegate;
                if (delegateToUse == null) {
                    // 把原来的查找IOC容器的代码注释掉
                    // WebApplicationContext wac = findWebApplicationContext();
                    // 按我们自己的需要重新编写
                    // 1、获取 servletContext
                    ServletContext servletContext = getServletContext();
                    // 2、拼接springMvc将IOC容器存入servletContext域的时候使用的属性
                    String servletName = "dispatcherServlet";
                    String attrName = FrameworkServlet.SERVLET_CONTEXT_PREFIX + servletName;
                    // 3、根据attrName 从ServletContext域中获取IOC容器对象
                    WebApplicationContext  wac = (WebApplicationContext) servletContext.getAttribute(attrName);
                    if (wac == null) {
                        throw new IllegalStateException("No WebApplicationContext found: " +
                                "no ContextLoaderListener or DispatcherServlet registered?");
                    }
                    delegateToUse = initDelegate(wac);
                }
                this.delegate = delegateToUse;
            }
        }

        // Let the delegate perform the actual doFilter operation.
        invokeDelegate(delegateToUse, request, response, filterChain);
    }

声明:纯情阿丁|版权所有,违者必究|如未注明,均为原创|本网站采用BY-NC-SA协议进行授权

转载:转载请注明原文链接 - 【异常】:No Bean Named ‘springSecurityFilterChain’ is Defined


阿丁在Coding,等你成为我的朋友!