1、基于动态代理实现
动态代理实现基本方式:https://blog.youkuaiyun.com/qq_34577961/article/details/128162372
2、面向切面AOP
2.1、基本步骤思路
1、引入依赖
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 {
@Override
public int add(int i, int j) {
int res = i + j ;
return res;
}
@Override
public 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 {
@Test
public 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/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://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>