项 | 描述 |
---|---|
Aspect | 一个模块具有一组提供横切需求的 APIs。例如,一个日志模块为了记录日志将被 AOP 方面调用。应用程序可以拥有任意数量的方面,这取决于需求。 |
Join point | 在你的应用程序中它代表一个点,你可以在插件 AOP 方面。你也能说,它是在实际的应用程序中,其中一个操作将使用 Spring AOP 框架。 |
Advice | 这是实际行动之前或之后执行的方法。这是在程序执行期间通过 Spring AOP 框架实际被调用的代码。 |
Pointcut | 这是一组一个或多个连接点,通知应该被执行。你可以使用表达式或模式指定切入点正如我们将在 AOP 的例子中看到的。 |
Introduction | 引用允许你添加新方法或属性到现有的类中。 |
Target object | 被一个或者多个方面所通知的对象,这个对象永远是一个被代理对象。也称为被通知对象。 |
Weaving | 把方面连接到其它的应用程序类型或者对象上,并创建一个被通知的对象。这些可以在编译时,类加载时和运行时完成。 |
在Spring AOP中支持4中类型的通知:
1:before advice 在方法执行前执行。
2:after returning advice 在方法执行后返回一个结果后执行。
3:after throwing advice 在方法执行过程中抛出异常的时候执行。
4:Around advice 在方法执行前后和抛出异常时执行,相当于综合了以上三种通知。
在以上几种示例中,能与整个流程交互的是 Around ,他提供了 ProceedingJoinPoint 这个参数,通过这个参数可以获取返回值、调用方法、调用结果等信息,也可以通过 pjp.proceed() 来决定流程的走向;(一个建议,因为 execution 匹配的方式,建议请求方式都以公共的、统一的参数名称来作为第一个参数)
下图是aop的生命周期
@Aspect
public class AopLog {
@Pointcut(
value = "execution(* com.eifel.spring.aop.service.*(..))"
+ "&&(args(requestParam,*,*) || args(requestParam) || args(requestParam,*))",
argNames = "requestParam")
private void request(RequestParam requestParam) {
}
@Around("request(requestParam)")
public Result log(ProceedingJoinPoint pjp, RequestParam requestParam) throws Throwable {
long startTime = System.currentTimeMillis();
String className = pjp.getTarget().getClass().getName();
String methodName = pjp.getSignature().getName();
String logName = className + "." + methodName;
try {
Result result = (Result)pjp.proceed();
String message = result.getMessage() == null ? "success" : result.getMessage();
loger.bizLog("|{0}|" + logName + "|{1}|{2}-{3}#{4}",
requestParam.getNation(), result.isSuccess(), requestParam.getShopId(), message,
System.currentTimeMillis() - startTime);
return result;
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return null;
}
}