SpringAop应用
1. 引言
为什么要使用Aop?贴一下较为官方的术语:
在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方 式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个 热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑 的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高 了开发的效率。
2. Aop相关概念
照例,先给出一个官方标准解释
Aspect
(切面): Aspect 声明类似于 Java 中的类声明,在 Aspect 中会包含着一些 Pointcut 以及相应的 Advice。Joint point
(连接点):表示在程序中明确定义的点,典型的包括方法调用,对类成员的访问以及异常处理程序块的执行等等,它自身还可以嵌套其它 joint point。Pointcut
(切点):表示一组 joint point,这些 joint point 或是通过逻辑关系组合起来,或是通过通配、正则表达式等方式集中起来,它定义了相应的 Advice 将要发生的地方。Advice
(增强):Advice 定义了在Pointcut
里面定义的程序点具体要做的操作,它通过 before、after 和 around 来区别是在每个 joint point 之前、之后还是代替执行的代码。Target
(目标对象):织入Advice
的目标对象.。Weaving
(织入):将Aspect
和其他对象连接起来, 并创建Advice
d object 的过程
最近有个需求,需要统计用户调用接口的持续时间,分析时间较长的接口然后对其进行优化。代码逻辑就是在每个接口前后记录一下时间,入库。此时,但又不可能在每个接口前后都写这样的代码,这是,想到了代理,在每次调用接口时对其前后记录时间。静态代理肯定不行,这和在每个接口前后写没有区别。那就用动态代理时间实现,动态代理不就是AOP嘛。这样就只用写一个统计类了。这个类就相当于一个切面(Aspect)。代码里我到底要做什么?比如说在接口执行前需记录时间(前置增强),接口执行后需执行时间(后置增强)。那我就写几个方法,这几个方法就是Advice(增强)。要做什么写好了,那到底在哪运行?就在Pointcut中指定要在哪运行,这就是Aop中的切点。
如图,3条竖立的红线框代表切面,与业务线相交的地方代表切点,红线框中的a(),b()...这些方法代表通知。----------
3. Aop统计各个接口运行时长
理清思路,代码编写其实很简单。下面贴一下我自用的统计接口时长的代码。
package com.boot.beanConfig; import com.boot.mapper.UserMessageLogMapper;
import com.boot.pojo.UserMessageLog;
import com.boot.service.LoggerService;
import com.boot.service.UserService;
import com.boot.util.JwtParseUtil;
import com.boot.util.MessageException;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; /**
* @Author xiabing5
* @Create 2019/8/13 10:31
* @Desc 日志记录切面类
**/
@Component
@Aspect
public class AopLoggerAspect { private static final Logger logger = Logger.getLogger(AopLoggerAspect.class); @Autowired
private LoggerService loggerService; // 定义切面的匹配规则
@Pointcut("execution(* com.boot.service.impl.*(..)) public void pointCut() { } @Before("pointCut()")
public void doBefore(JoinPoint joinPoint) { } @After("pointCut()")
public void doAfter(JoinPoint joinPoint) { } @AfterReturning(pointcut = "pointCut()",returning = "result")
public void afterReturn(JoinPoint joinPoint, Object result) { } @AfterThrowing(pointcut = "pointCut()",throwing = "throwable")
public void afterThrowing(JoinPoint joinPoint, Throwable throwable) { } // 环绕增强
@Around("pointCut()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
HttpServletRequest httpServletRequest = getHttpServletRequest();
String token = httpServletRequest.getHeader("token");
if(token == null) {
Object result = joinPoint.proceed();
return result;
}
String methodName = joinPoint.getSignature().getName(); Long startTimeMills = System.currentTimeMillis();
Object result = joinPoint.proceed(); // 调用proceed()方法会真正的执行实际被代理的方法
Long endTimeMills = System.currentTimeMillis();
Long runTime = endTimeMills-startTimeMills; // 插入操作记录
try{
// loggerService.insertUserMessageLog(userMessageLog);
}
catch (Exception e) {
e.printStackTrace();
logger.error("Method Name : [" + methodName + "] ---> ERROR");
}
return result;
} }
Aop统计接口调用时长
在实现Aop时,有个小坑。我的接口都添加了事物,对于查找的接口添加的是只读事物,但使用Aop统计接口时长时,代理执行接口后,需要将记录写入到数据库。这样就会报错,因为只读事物不能写呀!!!所以,我在记录日志的接口上修改了事物的传播特性。因为我事物传播特性默认是PROPAGATION_REQUIRED,即有事物就加入此事物。所以我的写操作加入到了只读事物---- 修改内容见下。不明白我说的也没关系---忽略我即可----
@Transactional(propagation= Propagation.NOT_SUPPORTED)
public void insertUserMessageLog(UserMessageLog userMessageLog) {
userMessageLogMapper.insert(userMessageLog);
}
修改插入操作的事物传播属性
4. 总结
Aop能很大程度降低代码耦合度!在实现记录日志时,发现了一个问题,即aop不能记录方法内的方法。因为Aop本质上就相当于是个代理----------好了,秒懂。
SpringAop应用的更多相关文章
- Spring-AOP实践 - 统计访问时间
公司的项目有的页面超级慢,20s以上,不知道用户会不会疯掉,于是老大说这个页面要性能优化.于是,首先就要搞清楚究竟是哪一步耗时太多. 我采用spring aop来统计各个阶段的用时,其中计时器工具为S ...
- Spring-Aop入门
(一)Aop术语定义 1.通知(advice) 通知定义了切面要做什么工作,即调用的方法,同时定义了什么时候做这些工作,即以下五种类型 (1)前置通知(Before) :在目标方法调用之前执行切面方法 ...
- 转-springAOP基于XML配置文件方式
springAOP基于XML配置文件方式 时间 2014-03-28 20:11:12 CSDN博客 原文 http://blog.csdn.net/yantingmei/article/deta ...
- SpringAOP详解(转载大神的)
AOP(Aspect-Oriented Programming)这个东西,名字与 OOP 仅差一个字母,其实它是对 OOP 编程方式的一种补充,并非是取而代之.翻译过来就是"面向方面编程&q ...
- spring-aop学习
SpringAOP学习 author:luojie 1. AOP中的基本概念 AOP的通用术语,并非spring java所特有.很遗憾AOP的术语不是特别的直观.但如果让Spring java来 ...
- SpringAOP之静态代理
一.SpringAOP: ⒈AOP:Aspect Oriented Programming 面向切面编程, 实现的是核心业务和非核心业务之间的的分离,让核心类只做核心业务,代理类只做非核心业务. ⒉ ...
- springaop实现登陆验证
1.首先配置好springmvc和springaop 2.先写好登陆方法,通过注解写代理方法 通过代理获得登陆方法的参数方法名,然后再aop代理方法内进行登陆验证 贴出代码 package com.h ...
- spring-aop示例
具体案例放在github上,主要是jar包在上面 https://github.com/guoyansi/spring-aop-example knights.xml <?xml version ...
- 使用SpringAop 验证方法参数是否合法
(原文地址:http://blog.csdn.net/is_zhoufeng/article/details/7683194) 1.依赖包 aspectjweaver.jar 其中Maven的配 ...
- 关于SpringAOP的XML方式的配置
AOP(XML)[理解][应用][重点] 1.AOP基础实例 A.导入jar包 核心包(4个) 日志(2个) AOP(4个) Spring进行AOP开发(1个) ...
随机推荐
- spring实战学习笔记(一)spring装配bean
最近在学习spring boot 发现对某些注解不是很深入的了解.看技术书给出的实例 会很疑惑为什么要用这个注解? 这个注解的作用?有其他相同作用的注解吗?这个注解的运行机制是什么?等等 spring ...
- Oracle中ROWNUM伪列和ROWID伪列的用法与区别
做过Oracle分页的人都知道由于Oracle中没有像MySql中limit函数以及SQLServer中的top关键字等,所以只能通过伪列的方式去满足分页功能,在此,不谈分页方法,只从根本上去介绍这两 ...
- Java集合系列(四):HashMap、Hashtable、LinkedHashMap、TreeMap的使用方法及区别
本篇博客主要讲解Map接口的4个实现类HashMap.Hashtable.LinkedHashMap.TreeMap的使用方法以及三者之间的区别. 注意:本文中代码使用的JDK版本为1.8.0_191 ...
- Jmeter 接口测试参数处理
问题: 一.签名参数sign算法由文字描述,算法需自己编写 二. 参数param_json为变化的json串(json串内订单号唯一) 解决: 一. 签名sign: 1. 手动拼接后在https:// ...
- 启动Eclipse提示找不到虚拟机
由于硬盘坏了,把所有东西都清光了,今天重新安装Eclipse,出现了一点小插曲 安装的时候出现了这个画面,以前安装也是照着[软件安装管家]的发布装的,幸好还懂得几个英文单词,看了一下提示信息,直译:[ ...
- Map集合的遍历(利用entry接口的方式)
核心思想: 调用map集合中的方法entrySet()将集合中的映射关系存放在Set集合中. 迭代Set集合 获取出的Set集合的元素是映射关系对象 通过映射关系对象方法的getKey(),getVa ...
- 循环 与 分支语句 和 字符函数库cctype 文件简单处理
循环 for循环 while循环 do while循环 通常,入口条件循环比出口条件循环好,因为循环开始前对条件进行检查 c++11基于范围的for循环 对数组(或容器类,如:vector和a ...
- Django对接SQL Server服务
1.环境描述环境:Win7 + Django2.1.10 + SQL Server 2014 + Python3.6 + PyCharm 2017.2.3 x64 2.安装插件由于Django默认是不 ...
- (四十五)c#Winform自定义控件-水波图表
前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kwwwvagaa/NetWinformControl 码云:ht ...
- Java设计模式14:建造者模式
什么是建造者模式 发现很多框架的源码使用了建造者模式,看了一下觉得挺实用的,就写篇文章学习一下,顺便分享给大家. 建造者模式是什么呢?用一句话概括就是建造者模式的目的是为了分离对象的属性与创建过程,是 ...