AOP学习笔记
AOP学习笔记
作用
AOP在Spring中的常用的作用是对执行方法进行增强,可以实现一些额外的功能
常见名词
概念 | 含义 |
---|---|
Aspect | 切面 |
Joint Point | 连接点,Spring AOP中总是代表一次方法执行 |
Advice | 通知,在连接点执行的动作 包括Before After Around等 |
Pointcut | 切入点,说明如何匹配连接点 |
Introduction | 为现有类型声明额外的方法和属性 |
Target Object | 目标对象 |
AOP Proxy | AOP代理对象 |
Weaving | 连接切面与目标对象或类型创建代理的过程 |
使用示例
本例中示范了以下内容:
- aop对于环绕通知的使用
- 使用spel表达式获取动态参数
代码
拦截方法:
// 实体类
public class NewOrderRequest {
private String customer;
private List<String> items;
}
// 注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ParamPrint {
String param() default "";
}
// 切面,进行环绕拦截,并将参数动态传入注解
@ParamPrint(param="#newOrder.customer + #newOrder.items[0]")
public CoffeeOrder create(@RequestBody NewOrderRequest newOrder) {
log.info("Receive new Order {}", newOrder);
Coffee[] coffeeList = coffeeService.getCoffeeByName(newOrder.getItems())
.toArray(new Coffee[] {});
return orderService.createOrder(newOrder.getCustomer(), coffeeList);
}
切面实现:
@Component
@Aspect
public class ParamPrintAspect {
// 作用点:ParamPrint注解
@Pointcut("@annotation(geektime.spring.springbucks.waiter.aspect.ParamPrint)")
public void pointCut(){}
// @Before("pointCut()")
// public void beforeCut(JoinPoint joinPoint) {
// System.out.println("before" + joinPoint);
// }
//
// @After("pointCut()")
// public void afterCut(JoinPoint joinPoint) {
// System.out.println("after" + joinPoint);
// }
//环绕通知
@Around("pointCut()")
public Object aroundCut(ProceedingJoinPoint joinPoint) {
Object result = null;
System.out.println("=======before=======");
getSpelParam(joinPoint);
try {
System.out.println(Arrays.toString(joinPoint.getArgs()));
joinPoint.proceed(joinPoint.getArgs());
} catch (Throwable e) {
System.out.println(e.getMessage());
}
System.out.println("=======after=======");
return result;
}
//通过spel表达式绑定参数结果
public void getSpelParam(ProceedingJoinPoint joinPoint) {
// 通过joinPoint获取被注解方法
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
ParamPrint paramPrint = methodSignature.getMethod().getAnnotation(ParamPrint.class);
String param = paramPrint.param();
Method method = methodSignature.getMethod();
//创建解析器
SpelExpressionParser parser = new SpelExpressionParser();
//设置解析上下文(有哪些占位符,以及每种占位符的值)
EvaluationContext context = new StandardEvaluationContext();
//获取参数值
Object[] args = joinPoint.getArgs();
//获取运行时参数的名称
DefaultParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer();
String[] parameterNames = discoverer.getParameterNames(method);
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i],args[i]);
}
//解析,获取替换后的结果
//获取表达式
Expression expression = parser.parseExpression(param);
String result = expression.getValue(context).toString();
}
}
宝剑锋从磨砺出 梅花香自苦寒来