前景
两个切面类:【记录日志】和【判断参数】,分别对应顺序 @Order(0) 和@Order(1) 。
本文只是将重点说下 执行顺序 这么回事哈哈哈
代码
【业务类】
/**
* 登录控制器
*/
@Controller
public class LoginController {
//向外面抛出异常
public void loginWithThrow(String username, String password) throws Exception {
if (username == null || password == null) {
throw new Exception("登录信息不可为空啊");
}
System.out.println("LoginController#login...");
}
//抛出异常自己捕获的情况
public void loginWithTryCatch(String username, String password) {
try{
if (username == null || password == null) {
throw new Exception("登录信息不可为空啊");
}
System.out.println("LoginController#login...");
}catch (Exception e){
e.printStackTrace();
}
}
}
【切面类】
/**
* 输出日志注解
*/
@Order(0)
@Aspect
@Component
public class LogAspect {
//抽出共通的execution用的
//com.yuki.demo.aop.aspect 包或者子包下所有类的方法
@Pointcut("execution(* com.yuki.demo.aop.aspect..*.*(..))")
public void pointcut(){
}
//前置通知
// @Before("execution(public void com.yuki.demo.aop.aspect.LoginController.*(String,String))")
@Before("pointcut()")
public void before() {
System.out.println("LogAspect#before...");
}
//环绕通知
//ProceedingJoinPoint 只有环绕通知有
@Around("execution(public void com.yuki.demo.aop.aspect.LoginController.*(String,String))")
public void around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("LogAspectA#around开始...");
//代理方法的执行,如果没有joinPoint.proceed() ,则前置通知@Before 不会执行,其它的通知正常
joinPoint.proceed();
//执行方法之后,如果joinPoint.proceed() 抛出了异常,则该句不会执行,抛出异常后直接跳出了aroud方法了
System.out.println("LogAspectA#around结束...");
}
//后置通知(只要连接点被执行,不管是否抛出异常)
@After("execution(public void com.yuki.demo.aop.aspect.LoginController.*(String,String))")
public void after() {
System.out.println("LogAspect#after...");
}
//异常通知(只有在joinPoint.proceed()方法执行向外面抛出了异常,才会执行该通知)
@AfterThrowing("execution(public void com.yuki.demo.aop.aspect.LoginController.*(String,String))")
public void afterThrowing() {
System.out.println("LogAspect#afterThrowing...");
}
//正常的返回通知通知(正常结束了才会执行该通知)
@AfterReturning("execution(public void com.yuki.demo.aop.aspect.LoginController.*(String,String))")
public void afterReturning() {
System.out.println("LogAspect#afterReturning...");
}
}
【切面类】
/**
* 判断请求参数的sign是否正确的 切面类
*/
@Order(1)
@Aspect
@Component
public class SignAspect {
@Around("execution(public void com.yuki.demo.aop.aspect.LoginController.*(String,String))")
public void around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("SignAspect#around开始...");
joinPoint.proceed();
System.out.println("SignAspect#around结束...");
}
}
【启动配置】
省略。。。非重点
【测试类】
@SpringBootTest
class AopApplicationTests {
@Autowired
private LoginController loginController;
@Test
void contextLoads() {
loginController.loginWithTryCatch("yuki", "1234");
}
}
【控制台输出】
LogAspectA#around开始...
LogAspect#before...
SignAspect#around开始...
LoginController#login...
SignAspect#around结束...
LogAspectA#around结束...
LogAspect#after...
LogAspect#afterReturning...