1.面向切面编程
什么是面向切面编程:
高类聚低耦合是面向对象设计的终极目标,但无论怎么设计有些耦合问题一定存在,就是有一些“沙子”被掺杂在系统中,比如校验权限、写日志,等等就只是一个方法调用,但是会被撒的遍地都是。这会面临一个问题,就是一旦这些方法在方法签名上有所修改,比如修改了方法名或者修改了入参,那么被撒了“沙子”的地方都要修改,搞得系统到处都要做修改。
面向切面编程就是为了解决这个问题,面向对象编程之后出现的一种新的编程方法,主要用于处理分散在系统中各处零碎的代码,使用面向切面编程的方法可以将这些零碎的代码收集起来进行集中管理,使得整个系统变得干净。
AOP中的一些概念:
通知(Advice):“沙子”,由两部分组成,这些"沙子"做什么和这些沙子"什么时候做"。
连接点(Join Point):撒"沙子"的点,是程序执行过程中能够应用通知的所有点。
切点(Poincut):掺“沙子”的点很多,切点就是一组连接点的集合。
切面(Aspect):切面=通知+切点。通知和切点共同定义了切面的全部内容——是什么,何时,何地完成功能。
2.Spring Boot中的AOP
Spring Boot中一般通过注解来使用AOP,代码示例如下:
@Aspect//声明这是一个切面 @Component//装入IOC容器 public class MyAspect { @Pointcut("execution(* com.tongweb.controller.*.*(..))")//定义切点 public void test() { } /** * @Description: 前置通知 * @Param: [joinPoint] 切点 * @return: void * @Author: ZouJiaNan * @Date: 2023/2/2 * @Time: 12:55 **/ @Before("test()") public void beforeAdvice(JoinPoint joinPoint) { System.out.println("joinPoint:"+joinPoint.getTarget()); System.out.println("beforeAdvice..."); } /** * @Description: 后置通知 * @Param: [joinPoint] 连接点 * @return: void * @Author: ZouJiaNan * @Date: 2023/2/2 * @Time: 12:56 **/ @After("test()") public void afterAdvice(JoinPoint joinPoint) { System.out.println("afterAdvice..."); } /** * @Description: 环绕通知 * @Param: [proceedingJoinPoint] 连接点 * @return: void * @Author: ZouJiaNan * @Date: 2023/2/2 * @Time: 12:56 **/ @Around("test()") public void aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) { System.out.println("before"); try { proceedingJoinPoint.proceed(); } catch (Throwable t) { t.printStackTrace(); } System.out.println("after"); } /** * @Description: * 异常通知,需要注意的是如果环绕通知和异常通知一起使用,要注意环绕通知中是否捕获了异常, * 本示例中环绕通知就捕获了异常,两者一同使用的话会造成异常通知失效。 * @Param: [joinPoint, ex] 连接点,所捕获的异常 * @return: void * @Author: ZouJiaNan * @Date: 2023/2/2 * @Time: 12:57 **/ @AfterThrowing(throwing = "ex",pointcut = "test()") public void afterThrowing(JoinPoint joinPoint,Throwable ex){ System.out.println(joinPoint+"出现异常:"+ex.getMessage()); } /** * @Description: 返回通知 * @Param: [joinPoint, ret] 连接点,返回值 * @return: void * @Author: ZouJiaNan * @Date: 2023/2/2 * @Time: 12:57 **/ @AfterReturning(returning = "ret", pointcut = "test()") public void doAfterReturning(JoinPoint joinPoint,Object ret){ System.out.println(joinPoint.getTarget()+"返回值 : " + ret); } }