Controller层的方法访问标志与Spring装配与AspectJ切面处理
最近在做AspectJ实现的日志模块,在spring配置中加入了<aop:aspectj-autoproxy/>,之后发现,只要有用到自定义注解的类,某些方法经MVC请求时就报空指针错误。
【症状】同一个类,该类中某些方法使用了AspectJ处理的自定义注解,结果某些方法访问正常,另一些方法报空指针错误。进一步debug发现autowired的对象为空,即注入失败。去掉<aop:aspectj-autoproxy/>一切正常。
【排查】1、观察问题类中方法的差异,难道说代理类要严格区分某一个RequestMapping、GetMapping、PostMapping?@ResponseBody?经测试,这种理由不存在的。。
2、IDE内运行项目导致?个人用的Eclipse,Tomcat clean,Maven Update Project,问题依旧。
3、用到了多于一个切面处理方式,导致代理过一次的类无法再次代理?我找到了这两篇文章,https://blog.csdn.net/u013803303/article/details/53113102,https://blog.csdn.net/niemingming/article/details/9064487,但也多少受其误导,我们的问题不是一事。
首先,我想要使用的切面类都是AspectJ方式。何况,项目中spring已经达到4.x版本,不应出现spring装配和AspectJ代理二者兼容性的问题。
4、注册的切面类bean有问题?我找到了这篇文章,https://www.cnblogs.com/leiOOlei/p/3713989.html,得知,
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
<context:annotation-config /> ,用于激活那些已经在spring容器里注册过的bean,而且仅能够在已经在已经注册过的bean上面起作用。对于没有在spring容器中注册的bean,它并不能执行任何操作。
<context:component-scan>除了具有<context:annotation-config />的功能之外,还可以在指定的package下扫描以及注册javabean ,自动将带有@component,@service,@Repository等注解的对象注册到spring容器中。
<context:annotation-config />和 <context:component-scan>同时存在的时候,前者会被忽略。同时哪怕是手动的注册了多个处理器,Spring仍然会尽最大努力避免重复,也就是那些@autowire,@resource等注入注解只会被注入一次。
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
的确,对于在配置中注册的切面类bean,其上的注解@Aspect,并不确定是否被激活了,于是我尝试在spring中加入<context:annotation-config />,问题依旧。
【原因】这是我观察到出现问题的方法,访问标志都是private。查阅资料得知,当Controller中方法为private修饰时,注入bean会失败。
但是,未引入<aop:aspectj-autoproxy/>元素时无此问题,想来这应该是spring 4.x版本装配bean时做的特殊处理。那么当aspectj再来代理时,估计其调用ASM解析时严格限制了访问标志,导致private方法的bean注入全部被忽略,同时public方法正常,也验证了代理是以方法为单位的(而不是类)。
【解决】如此,更改Controller层方法的访问标志为public即可。
【扩展】那么,如果存在多个切面类,如何确定它们执行的顺序呢?简单记忆切面类@order越小越先执行,最先执行的最后结束,详细参考这篇文章 https://blog.csdn.net/hxpjava1/article/details/55504513/,它验证了两个aop通知处理的顺序,其中before是否执行、before与around的先后、around与after的先后、after与afterReturning的先后,都很值得学习。
Controller层的方法访问标志与Spring装配与AspectJ切面处理的更多相关文章
- Spring实战(十二) Spring中注入AspectJ切面
1.Spring AOP与AspectJ Spring AOP与AspectJ相比,是一个功能比较弱的AOP解决方案. AspectJ提供了许多它不能支持的类型切点,如在创建对象时应用通知,构造器切点 ...
- SpringMVC的controller层的方法返回值
1.ModelAndView 既带着数据,又返回视图路劲 2.String 返回试图路径 model带数据 (官方或企业推荐使用此种方式 ,此方法符合解耦思想,即数据,视图,分离 MVC) 3. ...
- PowerMock+SpringMVC整合并测试Controller层方法
PowerMock扩展自Mockito,实现了Mockito不支持的模拟形式的单元测试.PowerMock实现了对静态方法.构造函数.私有方法以及final方法的模拟支持,对静态初始化过程的移除等强大 ...
- Spring AOP:面向切面编程,AspectJ,是基于注解的方法
面向切面编程的术语: 切面(Aspect): 横切关注点(跨越应用程序多个模块的功能)被模块化的特殊对象 通知(Advice): 切面必须要完成的工作 目标(Target): 被通知的对象 代理(Pr ...
- Spring AOP(面向切面示例)
什么是AOP?基本概念切面(aspect):横切关注点被模块化的特殊对象.通知(advice):切面必须要完成的工作.切面中的每个方向称之为通知.通知是在切面对象中的.目标(target):被通知的对 ...
- Spring学习--用 ASpectJ 注解实现 AOP
用 AspectJ 注解声明切面: 要在 Spring 中声明 AspectJ 切面 , 只需要在 IOC 容器中将切面声明为 bean 实例.当在 Spring IOC 容器中初始化 AsjectJ ...
- Spring中的面向切面编程(AOP)简介
一.什么是AOP AOP(Aspect-Oriented Programming, 面向切面编程): 是一种新的方法论, 是对传统 OOP(Object-Oriented Programming, 面 ...
- spring security 在controller层 方法级别使用注解 @PreAuthorize("hasRole('ROLE_xxx')")设置权限拦截 ,无权限则返回403
1.前言 以前学习的时候使用权限的拦截,一般都是对路径进行拦截 ,要么用拦截器设置拦截信息,要么是在配置文件内设置拦截信息, spring security 支持使用注解的形式 ,写在方法和接口上拦截 ...
- Spring框架Controller层(表现层)针对方法参数是Bean时HttpServletRequest绑定参数值问题解释
在做项目的时候,有一个需求是将数据库中的信息封装到实体类返回到jsp界面 传过来的参数只是实体类的id属性,然后根据id属性去查数据库,事情就是这样,然后 结果遇到很奇怪的事情,在jsp页面中使用EL ...
随机推荐
- Mysql优化总结(一)
一,前言 数据库(Database)是按照数据结构来组织.存储和管理数据的仓库. MySQL 是一个关系型数据库管理系统,由瑞典 MySQL AB 公司开发,目前属于 Oracle 公司.My ...
- Dart类型变量-表示信息
Dart执行入口 Dart要求以main函数作为执行的入口 Dart的变量和类型 在Dart中可以用var或者具体的类型来声明一个变量.当使用var定义变量时,表示类型是由编译器推断决定.使用静态类型 ...
- charles 发布Glist
本文参考:charles 发布Glist Publish Gist /发布代码段 选中某个文件,点击Publish Gist,如果你没有github,这个文件将被匿名发布,您也就无法删除它: 当然你可 ...
- ElasticSearch实战系列二: ElasticSearch的DSL语句使用教程---图文详解
前言 在上一篇中介绍了ElasticSearch集群和kinaba的安装教程,本篇文章就来讲解下 ElasticSearch的DSL语句使用. ElasticSearch DSL 介绍 Elastic ...
- Spring框架学习笔记(2)——面向切面编程AOP
介绍 概念 面向切面编程AOP与面向对象编程OOP有所不同,AOP不是对OOP的替换,而是对OOP的一种补充,AOP增强了OOP. 假设我们有几个业务代码,都调用了某个方法,按照OOP的思想,我们就会 ...
- 记一次jmeter从txt文本获取数值并给测试计划的变量赋值,jmeter永久性修改变量。
前言: 需要永久性的改变变量. 其实这个办法并不是最好的,但是是最容易实现的.后期可做成从数据库里直接取值. 赋值BeanShell import java.io.File; import java. ...
- 2019年十大开源WEB应用防火墙点评
2019年十大开源WEB应用防火墙点评 随着WEB应用的爆炸式成长和HTTPS加密的普及,针对网络应用层的攻击,像SQL注入.跨站脚本攻击.参数篡改.应用平台漏洞攻击.拒绝服务攻击等越来越多,传统的防 ...
- Robot Framework自定义测试库的作用域的理解
robot framework中,强大的测试库api支持,用户可根据实际需求定义测试库,导入后可使用自定义库中相应的关键字. 当自定义的测试库是类库,则需要考虑一个问题:类实例.用类实现的库可以有内部 ...
- Maven 梳理 -目录结构
Maven项目的目录约定 MavenProjectRoot(项目根目录) |----src | |----main | | |----java ——存放项目的.java文件 | | |----reso ...
- QT两个窗口相互切换
信号(signals)与槽(slots)是QT重要机制,例子使用了C++11 lambda表达式进行了信号与槽的连接. 实现两个窗口通过点击按钮完成互相切换,注意子窗口只能发送信号,不能处理,所有信号 ...