当项目中存在2个以上IOC容器时,初始化security框架时会抛出异常

spring ioc父容器  扫描service...

springMVC ioc子容器 扫描controller...

这个异常主要在于哪一个ioc来扫描WebAppSecurityConfig类,

分析问题:

如果spring 扫描 :则Filter在spring ioc容器中

如果springMVC扫描:则Filter在springMVC 容器中

通常情况下使用security都是对请求做权限控制,所以不能由spring ioc容器来进行扫描,进而衍生出下面的异常

 

分析问题所在:

首先明确三组件加载顺序:

首先contextLoaderListener初始化 创建Spring IOC容器

其次DelegatingFilterProxy初始化 查找ioc容器 创建bean
最后DispatcherServlet初始化 创建springMVC  IOC容器
 
通过debug调试可以确定,在DelegatingFilterProxy初始化时,会查找有没有ioc容器,如果有则继续查找有没有bean,没有bean则抛出上面的异常信息
当没有IOC容器时,则会放弃查找,在第一次请求发出时在次查找ioc容器,也就是dispatcherServlet初始化后再次进行查找,如果找不到ioc容器会抛异常,如果找到会继续查找是否有这个bean
遗憾的是,这次依然找不到,通过Debug调试源码发现,第二次查找时查的依然是spring ioc容器
这个常量表示了永远会找父容器;
两种解决方案
方案一:不使用contextLoaderListener,将两个IOC容器合二为一由DispatcherServlet加载所有spring配置文件
这样会造成DelegatingFilterProxy在初始化时,找不到ioc容器,则放弃,在第一次请求时spring的配置文件全部加载,这是在查找则有了,
问题点:会破坏现有程序结构,原本是 ContextLoaderListener 和 DispatcherServlet两个组件创建两个 IOC 容器,现在改成只有一个。
 
方案二:修改源码
方法:1.在初始化时直接跳过查找ioc容器的环节
   2.第一次请求时直接找springMVC容器  
在项目路径下创建同包同类名的DelegatingFilterProxy类
将249行注释掉
WebApplicationContext wac = findWebApplicationContext(); //查找ioc容器
添加自己写的代码
// 获取servletContext对象
ServletContext sc = this.getServletContext();
// 拼接SpringMVC将IOC容器存入servletContext域的时候使用的属性名
String servletName = "dispatcherServlet";
String attrName = FrameworkServlet.SERVLET_CONTEXT_PREFIX+servletName;
WebApplicationContext wac = (WebApplicationContext)sc.getAttribute(attrName);
servletName 具体是什么值参照自己项目中web.xml中配置的dispatcherServlet的servlet-name名;

这时security环境初步搭建完成!
 
posted on 2020-03-29 20:22  ha1998  阅读(386)  评论(0编辑  收藏  举报