Spring AOP aspect切面指北
创始人
2024-03-13 07:20:56
0

文章目录

  • Spring Aspect cheatsheet
  • 使用
  • Why?
    • 概念
      • Advice类型
    • PointCut常用示例
      • Advice使用示例
      • 一个完整的例子
  • 参考

Spring Aspect cheatsheet

放一些简单易用的spring aspect 语法手册。

使用

完整代码:spring-aop

  1. 引入库, 参考build.gradle
  2. 使用@Aspect@Configuration来标记Aspect。参考LogingAspect

Why?

就像之前写的btrace手册一样, 为了方便查找和实际操作,想分享一些关于写Aspect相关的cheatsheet。

概念

  1. Aspect

    作为某个关注点、横切面在许多类的模块化集合。比如事务管理@Transactional就是在企业应用中事务相关的的横切面。或者某个用来记录日志的切面。一般情况下切面会包含一个完整
    的有意义的集合。一般会包含Pointcut定义和Advice定义。
  2. Join Point

    代表某个程序执行的点。在spring中代表某个方法的执行点。
  3. Advice

    在某个特殊的Join Point,Aspect采取的操作。包含不同的类型(around,before,after)。许多aop框架包括
    spring用拦截器来实现Advice,并且维护一个拦截器链来处理某个JointPoint的多个Advice。
  4. Pointcut

    定义满足某些定义条件的方法切面。Advice将在所有满足Pointcut的JoinPoint执行。比如Pointcut可以定义为
    在所有的Controller方法上执行(within(com.example.controller.*))。本文也将提供更多的例子方便查找。
  5. Introduction

    以类为基础去添加新的方法或者属性。比如可以为某些bean引入一个属性IsModified来方便实现缓存。
  6. Target object

    等着被aspect增强的类对象(也叫advised object)。因为spring用代理来实现的,所以这个也叫被代理对象。
  7. AOP proxy
    `
    为了实现aspect,通过JDK动态代理,或者cglib代理实现的增强过的对象。
  8. Weaving

    将多个aspect和真正的应用内组合在一起的过程, 可以在编译时(aspectj compiler),加载时,运行时(spring aop)实现。

Advice类型

  1. Before
  2. AfterReturning
  3. AfterThrowing
  4. Around

    around advice会有一个ProceedingJoinPoint参数.这是最强的一类advice。它提供proceed方法来
    调用原有逻辑。其他的几个Advie都是类似于只读型的, 只提供了一个JoinPoint类型的参数。

PointCut常用示例

示例解释
within(com.xyz.service.*)执行com.xyz.service(不包括子包)的所有类的方法
within(com.xyz.service..*)执行com.xyz.service(包括子包)的所有类的方法
this(com.xyz.service.AccountService)执行实现了AccountService的接口的类
execution(* com.example.springaop.controller.*.*(..))执行
execution(public * *(..))执行所有public方法
execution(* set*(..))执行所有方法名以set开始的方法
execution(* com.xyz.service.AccountService.*(..))执行所有在com.xyz.service.AccountService类里面的方法。
execution(* com.xyz.service.*.*(..))执行所有在com.xyz.service里面的方法(不包括子包)
execution(* com.xyz.service..*.*(..))执行所有在com.xyz.service里面的方法(包括子包)
@within(org.springframework.transaction.annotation.Transactional)某个类具有@Transactional注解
@annotation(org.springframework.transaction.annotation.Transactional)某个方法具有@Transactional注解

具体语法:
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern?)

Advice使用示例

  1. Before
    方法开始执行前,可以使用JoinPoint获取当前执行方法的状态。后续几个都可以获取该参数。
    @Before("execution(* com.xyz.myapp.dao.*.*(..))")public void doAccessCheck(JoinPoint jp) {}
  1. AfterReturning

    正常返回后:

    @AfterReturning(pointcut="com.xyz.myapp.CommonPointcuts.dataAccessOperation()",returning="retVal")public void doAccessCheck(Object retVal) {// ...}
    
  2. AfterThrowing

    抛异常后:

    @AfterThrowing(pointcut="com.xyz.myapp.CommonPointcuts.dataAccessOperation()",throwing="ex")
    public void doRecoveryActions(DataAccessException ex) {// ...
    } 
    
  3. Arround
    环绕通知可以使用ProceedingJoinPoint.proceed 来调用原始的实现。

   @Around("com.xyz.myapp.CommonPointcuts.businessService()")public Object timing(ProceedingJoinPoint jp) throws Throwable {// start stopwatchObject retVal = jp.proceed(); // stop stopwatchreturn retVal;}   
  1. 给Advice传参数。
    除了上面的JoinPoint可以拿到参数外,还可以用如下的方式拿到:
@Before("com.xyz.myapp.CommonPointcuts.dataAccessOperation() && args(account,..)")
public void validateAccount(Account account) {// ...
}

上面例子中account是第一个参数。 当然dataAccessOperation指定的PointCut必须保证有至少一个参数。

  1. Advice的顺序
    按照下面顺序执行:
@Around, @Before, @After, @AfterReturning, @AfterThrowing

不同Aspect的还可以通过@Order指定顺序

一个完整的例子

用来统计运行时长和记录请求的例子:

package com.example.springaop;import org.aspectj.lang.*;
import org.aspectj.lang.annotation.*;
import org.springframework.context.annotation.*;import java.util.*;@Configuration
@Aspect
public class LogingAspect {@Pointcut("within(com.example.springaop.controller.*)")public void ctrlMethod() {}@Pointcut("execution(public * *(..)) ")public void publicMethod() {}@Around("ctrlMethod() && publicMethod()")public Object loggingAndTiming(ProceedingJoinPoint jp) throws Throwable {long t1 = System.currentTimeMillis();String className = jp.getSignature().getDeclaringTypeName();String methodName = jp.getSignature().getName();String args = Arrays.toString(jp.getArgs());try {return jp.proceed();} catch (Throwable e) {throw e;}finally {System.out.println(String.format("%s.%s with args: %s , cost time: %d",className, methodName, args, System.currentTimeMillis() - t1));}}
}

参考

  1. spring官网文档

相关内容

热门资讯

求经典台词和经典旁白 求经典台词和经典旁白谁有霹雳布袋戏里的经典对白和经典旁白啊?朋友,你尝过失去的滋味吗? 很多人在即将...
小王子第二章主要内容概括 小王子第二章主要内容概括小王子第二章主要内容概括小王子第二章主要内容概括
爱情睡醒了第15集里刘小贝和项... 爱情睡醒了第15集里刘小贝和项天骐跳舞时唱的那首歌是什么谢谢开始找舞伴的时候是林俊杰的《背对背拥抱》...
世界是什么?世界是什么概念?可... 世界是什么?世界是什么概念?可以干什么?物质的和意识的 除了我们生活的地方 比方说山 河 公路 ...
全职猎人中小杰和奇牙拿一集被抓 全职猎人中小杰和奇牙拿一集被抓动画片是第五十九集,五十八集被发现,五十九被带回基地,六十逃走
“不周山”意思是什么 “不周山”意思是什么快快快快......一座山,神话里被共工撞倒了。
《揭秘》一元一分15张跑得快群... 一元一分麻将群加群主微【ab120590】【tj525555】 【mj120590】等风也等你。喜欢...
玩家必看手机正规红中麻将群@2... 好运连连,全网推荐:(ab120590)(mj120590)【tj525555】-Q号:(QQ443...
始作俑者15张跑的快群@24小... 微信一元麻将群群主微【ab120590】 【tj525555】【mj120590】一元一分群内结算,...
《重大通知》24小时一元红中麻... 加V【ab120590】【tj525555】【mj120590】红中癞子、跑得快,等等,加不上微信就...
盘点一下正规一块红中麻将群@2... 一元一分麻将群加群主微:微【ab120590】 【mj120590】【tj525555】喜欢手机上打...
(免押金)上下分一元一分麻将群... 微【ab120590】 【mj120590】【tj525555】专业麻将群三年房费全网最低,APP苹...
[解读]正规红中麻将跑的快@群... 微信一元麻将群群主微【ab120590】 【tj525555】【mj120590】一元一分群内结算,...
《普及一下》全天24小时红中... 微【ab120590】 【mj120590】【tj525555】专业麻将群三年房费全网最低,APP苹...
优酷视频一元一分正规红中麻将... 好运连连,全网推荐:(ab120590)(mj120590)【tj525555】-Q号:(QQ443...
《火爆》加入附近红中麻将群@(... 群主微【ab120590】 【mj120590】【tj525555】免带押进群,群内跑包包赔支持验证...
《字节跳动》哪里有一元一分红中... 1.进群方式-[ab120590]或者《mj120590》【tj525555】--QQ(QQ4434...
全网普及红中癞子麻将群@202... 好运连连,全网推荐:(ab120590)(mj120590)【tj525555】-Q号:(QQ443...
「独家解读」一元一分麻将群哪里... 1.进群方式《ab120590》或者《mj120590》《tj525555》--QQ(4434063...
通知24小时不熄火跑的快群@2... 1.进群方式《ab120590》或者《mj120590》《tj525555》--QQ(4434063...