项目当中需要对用户操作菜单的行为记录日志,用SpringAOP写了个大概实现,切点是采用注解的方式,用包名的方式虽然也可以达到相同的效果,但是不如注解方式灵活方便。
不多说,直接上代码,此处只是简单写写实现原理。
工程目录:
pom.xml引入以下依赖:
<!-- 热部署模块 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> <!-- 这个需要为 true 热部署才有效 --> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- spring-boot aop依赖配置引入 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
注解:
@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited public @interface Action { String description() default "no description"; }
Controller类:
/** * @auther: gaopeng */ @RestController public class AspectController { /** * 走切面 * @return */ @GetMapping("/test") @Action(description = "执行了test操作菜单") public String test(){ return "method return"; } /** * 不走切面 */ @GetMapping("/test1") private void test1(){ } /** * 走切面,抛异常 */ @GetMapping("/throws") @Action(description = "执行了throws菜单但是抛了异常") public void throwsException(){ throw new RuntimeException(); } }
切面类:
/** * @auther: gaopeng */ @Aspect @Component public class TestAspect { /** * 切入点 */ // 此处的切点是注解的方式,也可以用包名的方式达到相同的效果 //@Pointcut("execution(public * com.gaopeng.springboot.mytest.controller.*.*(..))") @Pointcut("@annotation(com.gaopeng.springboot.mytest.annotation.Action)") public void execute(){ } /** * 前置通知 * @param joinPoint */ @Before(value ="execute()") public void Before(JoinPoint joinPoint) { System.out.println("执行方法之前"); } /** * 环绕通知 * @param proceedingJoinPoint * @return */ @Around(value ="execute()") public Object around(ProceedingJoinPoint proceedingJoinPoint) { System.out.println("环绕通知开始"); try { System.out.println("执行方法:" + proceedingJoinPoint.getSignature().getName()); MethodSignature signature =(MethodSignature) proceedingJoinPoint.getSignature(); Action action = signature.getMethod().getAnnotation(Action.class); System.out.println("菜单="+action.description()); Object object = proceedingJoinPoint.proceed(); System.out.println("环绕通知结束,方法返回:" + object); return object; } catch (Throwable e) { System.out.println("执行方法异常:" + e.getClass().getName()); return null; } } /** * 后置通知 * @param joinPoint */ @After(value ="execute()") public void After(JoinPoint joinPoint) { System.out.println("执行方法之后"); } /** * 后置通知,带返回值 * @param obj */ @AfterReturning(pointcut = "execute()",returning = "obj") public void AfterReturning(Object obj) { System.out.println("执行方法之后获取返回值:"+obj); } /** * 后置通知,异常时执行 * @param e */ @AfterThrowing(throwing = "e",pointcut = "execute()") public void doAfterThrowing(Exception e) { System.out.println("执行方法异常:"+e.getClass().getName()); } }
运行结果:
原文地址:https://www.cnblogs.com/gaopengpy/p/11897917.html
时间: 2024-10-09 21:17:08