aop的各个概念

切面:目标类以外的类就是切面




引入jar包

<!-- aop -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.1</version>
</dependency>



配置文件中开启基于注解的aop功能

<!-- 开启基于注解的aop功能 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>



AOP相关注解

@Before 前置通知 在目标方法开始之前执行的通知
@After 后置通知 在目标方法结束后执行的通知
@AfterReturning 返回通知 在目标方法正常结束时,才执行的通知
@AfterThrowing 异常通知 在目标方法出现异常时才执行的通知
@Around 环绕通知



通知方法的执行顺序

  • 正常执行:@Before,@After,@AfterReturning
  • 异常执行:@Before,@After,@AfterThrowing
try {
@Before
method.invoke(obj, args);
@AfterReturning
} catch() {
@AfterThrowing
} finally {
@After
}



切入点表达式语法

execution(访问权限符[public可以缺省] 返回值类型 方法全类名(参数列表))


切入点表达式通配符

*
  • 匹配一个或多个字符
  • 匹配任意一个参数
..
  • 匹配任意多个参数,任意类型参数
  • 匹配任意多层路径


例如

execution(* *..*Service*.*(..))

execution(* cn.javaex.hgo.action.*.controller..*.*(..))




实例

package cn.javaex.config;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

/**
* 统一日志管理
*
* @author 陈霓清
*/
@Aspect
@Component
public class LogAspect {

/**
* 抽取可重用的切入点表达式
*/
@Pointcut("execution(* cn.javaex.hgo.action.*.controller..*.*(..))")
public void aopLog() {

}

/**
* 前置通知:在目标方法开始之前执行的通知
* @param joinPoint
* @throws HgoException
*/
@Before("aopLog()")
public void doBefore(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();

System.out.println(methodName + "()==========>正常开始");
}

/**
* 返回通知:在目标方法正常结束时,才执行的通知
* @param joinPoint
*/
@AfterReturning("aopLog()")
public void doAfterReturning(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
System.out.println(methodName + "()==========>正常终了");
}

/**
* 异常通知:在目标方法出现异常时才执行的通知
* @param joinPoint
* @param ex 告诉spring哪个参数是用来接收异常的
*/
@AfterThrowing(pointcut="aopLog()", throwing="ex")
public void afterThrowing(JoinPoint joinPoint, Exception ex) {
String methodName = joinPoint.getSignature().getName();
System.out.println(methodName + "()==========>异常终了");
System.out.println("异常原因:" + ex);
}
}



环绕通知

/**
* 环绕通知
* @param pjp
* @return
* @throws Throwable
*/
@Around("aopLog()")
public Object myAround(ProceedingJoinPoint pjp) throws Throwable {
Object[] args = pjp.getArgs();

Object proceed = null;

try {
System.out.println("前置通知");

// 就是利用反射调用目标方法:method.invoke(obj, args);
proceed = pjp.proceed(args);

System.out.println("返回通知,返回值:"+proceed);
} catch (Exception e) {
System.out.println("异常通知");

throw new RuntimeException(e);
} finally {
System.out.println("后置通知");
}

// 调用反射后的返回值也一定要返回出去
return proceed;
}



回到顶部