在springmvc+shiro项目中使用druid监听controller层出现IllegalStateException异常

最近在做个spring+springmvc+shiro的整合,后面想再加个druid去监听spring,当去监听的controller层的时候就报出了IllegalStateException异常

异常信息大概如下:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.
lang.IllegalStateException: The mapped handler method class 'com.zjw.shiro.controller.UserController' is 
not an instance of the actual controller bean class 'com.sun.proxy.$Proxy26'. If the controller requires
 proxying (e.g. due to @Transactional), please use class-based proxying.
HandlerMethod details: 
Controller [com.zjw.shiro.controller.UserController]
Method [public java.lang.String com.zjw.shiro.controller.UserController.login(com.zjw.shiro.entity.User,
javax.servlet.http.HttpServletRequest,org.springframework.web.servlet.mvc.support.RedirectAttributes)]
Resolved arguments: 
[0] [type=com.zjw.shiro.entity.User] [value=com.zjw.shiro.entity.User@59943548]
[1] [type=org.apache.shiro.web.servlet.ShiroHttpServletRequest] [value=org.apache.shiro.web.servlet.ShiroHttpServletRequest@2a4b3e88]
[2] [type=org.springframework.web.servlet.mvc.support.RedirectAttributesModelMap] [value={}]

    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982)

异常信息大概意思就是,对controller使用了jdk代理,要求你使用基于类实现的代理,其实就是让你用CGLIB代理

我们再来看下出现报错信息的配置文件

druid相关配置


 
  
    
      com.zjw.shiro.controller.*
      com.zjw.shiro.service.*
      com.zjw.shiro.mapper.*
    
   



  

shiro相关配置

因为,与下面配置做对比,我们这里称为shiro配置1




 
   
 

出现异常肯定是配置文件出现了问题。
从我们上一篇文章《JDK和CGLIB生成动态代理类的区别以及Spring动态代理机制》可以知道,
Spirng的AOP的动态代理实现机制也是这两种:JDK动态代理和CGLib动态代理
一般而言Spring默认优先使用JDK动态代理技术,只有在被代理类没有实现接口时,才会选择使用CGLIB技术来实现AOP。
我们的controller层是没有实现接口,应该是用CGLIB代理,而spring的AOP会自动根据运行类选择 JDK 或 CGLIB 代理,那应该会自动选择CGLIB代理啊。
但我们的异常信息却要求是我们使用基于类实现的代理——CGLIB代理,所以可以肯定是现在我们使用上面配置文件,因为某些原因而导致我们使用了jdk代理。

从《spring的bean二次代理问题》和《springAOP应尽量避免自己创建AutoProxyCreator》之前这两篇文章可以知道,spring的配置文件配置不当,容易导致spring的bean二次代理问题,那么是不是我们配置文件也出现问题,所以导致了出现了多个ProxyCreator,出现了冲突,让controller层使用的是jdk代理,所以最后出现上面IllegalStateException异常呢?

从上面druid相关配置,我们可以看到
这句配置,从之前的《springAOP应尽量避免自己创建AutoProxyCreator》就可以知道,这句代码是会注册一个AutoProxyCreator、
而shiro相关配置有一句也定义了一个DefaultAdvisorAutoProxyCreator,而且因为proxy-target-class的缺省,那肯定使用的是jdk代理。
所以有可能是两个代理起了冲突,导致当我们druid想去监控controller的时候是使用jdk代理,jdk代理不能对类进行代理所以才报了llegalStateException异常。

为了验证这个说法,我们可以看下日志信息

AspectJAwareAdvisorAutoProxyCreator创建一个对UserController的CGLIB代理.png

我们定义的DefaultAdvisorAutoProxyCreator创建一个对UserController的JDK代理.png

从日志我们可以看到AspectJAwareAdvisorAutoProxyCreator创建一个对UserController的CGBLIB代理和我们定义的DefaultAdvisorAutoProxyCreator创建一个对UserController的JDK代理,一个UserController的bean有两个不同的代理,所以起了冲突。
毫无疑问,肯定是配置文件问题导致了bean的两次代理问题。

如何解决:

我们把配置文件修改一下再看日志会发生什么不同

druid配置保存不变,shiro还是自己创建DefaultAdvisorAutoProxyCreator,只是稍微做了修改
我们这里称为shiro配置2



  
                    

你可能感兴趣的:(在springmvc+shiro项目中使用druid监听controller层出现IllegalStateException异常)