@AspectJ的详细用法
在Spring AOP中目前只有执行方法这一个连接点,Spring AOP支持的AspectJ切入点指示符如下:
一些常见的切入点的例子
execution(public * * (. .)) 任意公共方法被执行时,执行切入点函数。
execution( * set* (. .)) 任何以一个“set”开始的方法被执行时,执行切入点函数。
execution( * com.demo.service.AccountService.* (. .)) 当接口AccountService 中的任意方法被执行时,执行切入点函数。
execution( * com.demo.service.. (. .)) 当service 包中的任意方法被执行时,执行切入点函数。
within(com.demo.service.) 在service 包里的任意连接点。
within(com.demo.service. .) 在service 包或子包的任意连接点。
this(com.demo.service.AccountService) 实现了AccountService 接口的代理对象的任意连接点。
target(com.demo.service.AccountService) 实现了AccountService 接口的目标对象的任意连接点。
args(java.io.Serializable) 任何一个只接受一个参数,且在运行时传入参数实现了 Serializable 接口的连接点
增强的方式:
@Before:方法前执行
@AfterReturning:运行方法后执行
@AfterThrowing:Throw后执行
@After:无论方法以何种方式结束,都会执行(类似于finally)
@Around:环绕执行
添加 PointCut类
该pointcut用来拦截test包下的所有类中的所有方法。
package com.aop.test1;
import org.aspectj.lang.annotation.Pointcut;
public class PointCuts {
@Pointcut(value = "within(com.aop.test1.*)")
public void aopDemo() {
}
}
添加Aspect类
该类中的advice将会用到上面的pointcut,使用方法请看各个advice的value属性。
package com.aop.test1;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class Aspect1 {
@Before(value = "test.PointCuts.aopDemo()")
public void before(JoinPoint joinPoint) {
System.out.println("[Aspect1] before advise");
}
@Around(value = "test.PointCuts.aopDemo()")
public void around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("[Aspect1] around advise 1");
pjp.proceed();
System.out.println("[Aspect1] around advise2");
}
@AfterReturning(value = "test.PointCuts.aopDemo()")
public void afterReturning(JoinPoint joinPoint) {
System.out.println("[Aspect1] afterReturning advise");
}
@AfterThrowing(value = "test.PointCuts.aopDemo()")
public void afterThrowing(JoinPoint joinPoint) {
System.out.println("[Aspect1] afterThrowing advise");
}
@After(value = "test.PointCuts.aopDemo()")
public void after(JoinPoint joinPoint) {
System.out.println("[Aspect1] after advise");
}
}
添加测试用Controller
添加一个用于测试的controller,这个controller中只有一个方法,但是它会根据参数值的不同,会作出不同的处理:一种是正常返回一个对象,一种是抛出异常(因为我们要测试@AfterThrowing这个advice)
package com.aop.test1;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping(value = "/aop")
public class AopTestController {
@ResponseStatus(HttpStatus.OK)
@RequestMapping(value = "/test", method = RequestMethod.GET)
public Result test(@RequestParam boolean throwException) {
// case 1
if (throwException) {
System.out.println("throw an exception");
throw new RuntimeException("mock a server exception");
}
// case 2
System.out.println("test OK");
return new Result() {
{
this.setId(111);
this.setName("mock a Result");
}
};
}
public static class Result {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
我们会看到输出的结果是:
[Aspect1] around advise 1 [Aspect1] before advisetest OK [Aspect1] around advise2 [Aspect1] after advise [Aspect1] afterReturning advise
异常情况,我们会看到输出的结果是:
[Aspect1] around advise 1 [Aspect1] before advise throw an exception [Aspect1] after advise [Aspect1] afterThrowing advise
正常情况:
异常情况:
@Component
@Aspect
public class CacheAspect {
@Around("execution(public * *(..)) and @annotation(checkCache)")
public Object get(ProceedingJoinPoint jp, CheckCache checkCache) throws Throwable {
}
@AfterReturning(pointcut = "@annotation(evictCache)", returning = "retval")
public void remove(JoinPoint jp, EvictCache evictCache, Object retval) {
}
}
转载于:https://blog.51cto.com/snowtiger/2053668