ssm项目springSecurityFilterChain找不到bean的问题
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'springSecurityFilterChain' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:687)
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1209)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:284)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1086)
at org.springframework.web.filter.DelegatingFilterProxy.initDelegate(DelegatingFilterProxy.java:327)
at org.springframework.web.filter.DelegatingFilterProxy.initFilterBean(DelegatingFilterProxy.java:235)
at org.springframework.web.filter.GenericFilterBean.init(GenericFilterBean.java:236)
at org.apache.catalina.core.ApplicationFilterConfig.initFilter(ApplicationFilterConfig.java:285)
at org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:266)
at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:108)
at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:4615)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5262)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:754)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:730)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:734)
at org.apache.catalina.startup.HostConfig.manageApp(HostConfig.java:1730)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:287)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:483)
这里是引用
这里是引用
明确三大组件启动顺序
1、ContextLoaderListener 初始化, 创建 Spring 的 IOC 容器
2、 DelegatingFilterProxy 初始化, 查找 IOC 容器、 查找 bean
3、 DispatcherServlet 初始化, 创建 SpringMVC 的 IOC 容器
这里是引用
解决方案一: 把两个 IOC 容器合二为一
不使用 ContextLoaderListener, 让 DispatcherServlet 加载所有 Spring 配置文件。
DelegatingFilterProxy 在初始化时查找 IOC 容器, 找不到, 放弃。
第一次请求时再次查找。
找到 SpringMVC 的 IOC 容器。
从这个 IOC 容器中找到所需要的 bean。
遗憾: 会破坏现有程序的结构。 原本是 ContextLoaderListener 和 DispatcherServlet
两个组件创建两个 IOC 容器, 现在改成只有一个。
这里是引用
解决方案二: 改源码
修改 DelegatingFilterProxy 的源码, 修改两处:
/*WebApplicationContext wac = findWebApplicationContext();
if (wac != null) {
this.delegate = initDelegate(wac);
}*/
// 把原来的查找 IOC 容器的代码注释掉
// WebApplicationContext wac = findWebApplicationContext();
// 按我们自己的需要重新编写
// 1.获取 ServletContext 对象
ServletContext sc = this.getServletContext();
// 2.拼接 SpringMVC 将 IOC 容器存入 ServletContext 域的时候使用的属性
名
String servletName = "springDispatcherServlet";
String attrName = FrameworkServlet.SERVLET_CONTEXT_PREFIX +
servletName;
// 3.根据 attrName 从 ServletContext 域中获取 IOC 容器对象
WebApplicationContext wac = (WebApplicationContext)
sc.getAttribute(attrName);