1、基于动态代理实现
动态代理实现基本方式:https://blog.csdn.net/qq_34577961/article/details/128162372
2、面向切面AOP
2.1、基本步骤思路
1、引入依赖
基本依赖配置https://blog.csdn.net/qq_34577961/article/details/129152040?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22129152040%22%2C%22source%22%3A%22qq_34577961%22%7D
2、创建接口及其实现类
package com.ruqi.aoptest;import org.aspectj.lang.annotation.Aspect;public interface InterfaceTool {int add(int i, int j);int mul(int i, int j);
}============================
import org.springframework.stereotype.Component;@Component
public class InterfacetoolImpl implements InterfaceTool {@Overridepublic int add(int i, int j) {int res = i + j ;return res;}@Overridepublic int mul(int i, int j) {int res = i - j ;return res;}
}
3、创建切面类,设置切入点和通知类型
设置切入点解释如图
切面类代码实现:
package com.ruqi.aoptest;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;@Aspect //表示为切面类
@Component
public class LogAspect {/*** 通知类型:* 前置类:@Before()* 返回类:@AfterReturning()* 异常类:@AfterThrowing()* 后置类:@After()* 环绕类:@Around()*/@Before(value = "execution(public int com.ruqi.aoptest.InterfacetoolImpl2.*(..))")public void beforeMethod(JoinPoint joinPoint){String methodName = joinPoint.getSignature().getName();System.out.println("这是一个前置操作,方法名为" + methodName);}@After(value = "execution(public int com.ruqi.aoptest.InterfacetoolImpl2.*(..))")public void afterMethod(JoinPoint joinPoint){String methodName = joinPoint.getSignature().getName();System.out.println("这是一个后置操作,方法名为" + methodName);}@AfterReturning(value = "execution(public int com.ruqi.aoptest.InterfacetoolImpl2.*(..))",returning = "result")public void afterrReturnMethod(JoinPoint joinPoint,Object result){
// result 参数名要和注解定义的名称一致String methodName = joinPoint.getSignature().getName();System.out.println("这是一个返回值操作操作,方法名为" + methodName + ",该方法的返回值为:" + result);}@AfterThrowing(value = "execution(public int com.ruqi.aoptest.InterfacetoolImpl2.*(..))", throwing = "exception")public void afterThrowingMethod(JoinPoint joinPoint,Throwable exception){
// exception 参数名要和注解定义的名称一致String methodName = joinPoint.getSignature().getName();System.out.println("这是一个异常值操作操作,方法名为" + methodName + ",该方法的异常信息为:" + exception);}@Around(value = "execution(public int com.ruqi.aoptest.InterfacetoolImpl2.*(..))")public Object aroundMethod(ProceedingJoinPoint joinPoint){Object result1 = null;String methodName = joinPoint.getSignature().getName();try{System.out.println("方法执行前的操作,相当于before()注解");result1 = joinPoint.proceed(); //获取目标方法的返回值System.out.println("方法执行前的操作,相当于before()注解");}catch (Throwable e){e.printStackTrace();System.out.println("方法出现异常的操作,相当于AfterThrowing()注解");}finally {System.out.println("方法后置的操作,相当于After()注解");}return result1; // 相当于AfterReturning()}
}
测试类:
package com.ruqi.aoptest;import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class Testcase {@Testpublic void testBefore(){ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");InterfaceTool bean = context.getBean(InterfaceTool.class);bean.add(1,2);}
}
4、切面切入点重写
package com.ruqi.aoptest;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;@Aspect //表示为切面类
@Component
public class LogAspect {@Pointcut(value = "execution(* com.ruqi.aoptest.InterfacetoolImpl2.*(..))")public void pointCut(){}@After(value = "pointCut()") // 同个切面可以直接使用方法,否则需要使用全路径
// @After(value = "com.ruqi.aoptest.LogAspect.pointCut()") public void afterMethod(JoinPoint joinPoint){String methodName = joinPoint.getSignature().getName();System.out.println("这是一个后置操作,方法名为" + methodName);}
}
5、有多个切面类时,可设置优先级
package com.ruqi.aoptest;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.junit.jupiter.api.Order;
import org.springframework.stereotype.Component;@Aspect //表示为切面类
@Component
public class LogAspectOrder {@Order(1) //数字越小,优先级越高@After(value = "pointCut()")public void afterMethod(JoinPoint joinPoint){System.out.println("优先级为第一");}@Pointcut(value = "execution(* com.ruqi.aoptest.InterfacetoolImpl2.*(..))")public void pointCut(){}
}
3、基于xml进行切面
1、将切面的相关注解删除后,使用xml配置即可
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- 开启组件扫描--><context:component-scan base-package="com.ruqi.aoptest"></context:component-scan> <!--配置切面类和切入表达式,以及相关通知--><aop:config><aop:aspect ref="logAspect"> <!--配置切面类,使用类名,首字母小写--><aop:pointcut id="pointcutId" expression="execution(public int com.ruqi.aoptest.InterfacetoolImpl2.*(..))"/> <!--配置切入表达式--> <aop:before method="beforeMethod" pointcut-ref="pointcutId"></aop:before><aop:after method="afterMethod" pointcut-ref="pointcutId"></aop:after><aop:after-returning method="afterReturnMethod" returning="result" pointcut-ref="pointcutId"></aop:after-returning><aop:after-throwing method="afterThrowingMethod" throwing="exception" pointcut-ref="pointcutId"></aop:after-throwing><aop:around method="aAroundMethod" pointcut-ref="pointcutId"></aop:around></aop:aspect></aop:config></beans>