概念
AOP(Aspect-OrientedProgramming,面向切面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。
(1)Aspect(切面):通常是一个类,里面可以定义切入点和通知
(2)JointPoint(连接点):程序执行过程中明确的点,一般是方法的调用
(3)Advice(通知):AOP在特定的切入点上执行的增强处理,有before,after,afterReturning,afterThrowing,around
(4)Pointcut(切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式
(5)AOP代理:AOP框架创建的对象,代理就是目标对象的加强。Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类
方法
前置通知:在我们执行目标方法之前运行(@Before)
后置通知:在我们目标方法运行结束之后 ,不管有没有异常(@After)
返回通知:在我们的目标方法正常返回值后运行(@AfterReturning)
异常通知:在我们的目标方法出现异常后运行(@AfterThrowing)
环绕通知:动态代理, 需要手动执行joinPoint.procced()(其实就是执行我们的目标方法执行之前相当于前置通知, 执行之后就相当于我们后置通知(@Around)
执行顺序:@Around→@Before→Method→@After
日志模块实现方法
1.第一步 新建一个自定义注解类
@Documented @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface OperationLogDetail { OperationTypeEnum operationTypeEnum(); }
配合注解可以实现具体功能,我用了一个枚举类来声明日志的类别
@OperationLogDetail(operationTypeEnum = OperationTypeEnum.BORROW_STICK_IN_APPLY)
2.定义Aop配置,此处的切点是注解的方式,也可以用包名的方式达到相同的效果
@Pointcut("@annotation(cn.om.prd.util.OperationLogDetail)") public void operationLog(){}
@After("operationLog()")
public void doAfter(JoinPoint joinPoint) {
long time=System.currentTimeMillis();
try {
time = System.currentTimeMillis() - time;
} finally {
try {
//方法执行完成后增加日志
addOperationLog(joinPoint);
}catch (Exception e){
log.error("LogAspect 操作失败:" + e.getMessage());
e.printStackTrace();
}
}
}
private void addOperationLog(JoinPoint joinPoint){
MethodSignature signature = (MethodSignature)joinPoint.getSignature();
//获取你注解中的枚举对象属性
signature.getMethod().getAnnotation(OperationLogDetail.class).operationTypeEnum().getCode();
signature.getMethod().getAnnotation(OperationLogDetail.class).operationTypeEnum().getType();
}