spring-aop
首先,准备一个接口以及其实现类
Calculator接口:src/main/java/com.atguigu.service/Calculator接口
package com.atguigu.service;public interface Calculator {int add(int i, int j);int sub(int i, int j);int mul(int i, int j);int div(int i, int j);
}
Calculator接口的实现类:src/main/java/com.atguigu.service/impl/CalculatorImpl.java
package com.atguigu.service.impl;import com.atguigu.service.Calculator;
import org.springframework.stereotype.Component;@Component
public class CalculatorImpl implements Calculator {@Overridepublic int add(int i, int j) {int ret = i + j;return ret;}@Overridepublic int sub(int i, int j) {int ret = i - j;return ret;}@Overridepublic int mul(int i, int j) {int ret = i * j;return ret;}@Overridepublic int div(int i, int j) {int ret = i / j;return ret;}
}
然后,写一个配置类JavaConfig.java
src/main/java/com.atguigu.config/JavaConfig.java
package com.atguigu.config;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;@Configuration
@ComponentScan("com.atguigu")
@EnableAspectJAutoProxy:开启aspectj的注解,等同于.xml配置文件的<aop:aspectj-autoproxy />
@EnableAspectJAutoProxy
public class JavaConfig {
}
再然后,写一个专门的切面表达式的类
src/main/java/com.atguigu.pointcut/MyPointCut.java
package com.atguigu.pointcut;import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;这是专门存储切点表达式类
@Component
public class MyPointCut {@Pointcut("execution(* com.atguigu.service.impl.*.*(..))")public void pc(){}@Pointcut("execution(* com..impl.*.*(..))")public void myPc(){}
}
再再然后,专门的增强方法
src/main/java/com.atguigu.advice/MyAdvice.java
package com.atguigu.advice;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;import java.lang.reflect.Modifier;在增强方法中,获取目标方法的信息* 1、获取目标方法的信息(方法名、参数、访问修饰符、所属的类信息...)在方法的形参列表里,加(JoinPoint joinPoint) import org.aspectj.lang.JoinPoint包下的JoinPoint就包含了目标方法的信息* 2、获取返回的结果,在 @AfterReturning 时在方法的形参列表里,加一个 returning = "ret",如下:@AfterReturning(value = "execution(* com..impl.*.*(..))", returning = "ret")public void afterReturning(JoinPoint joinPoint, Object ret){}* 3、获取异常一新,在 @AfterThrowing 时在方法的形参列表里,加一个throwing = "throwable",如下:@AfterThrowing(value = "execution(* com..impl.*.*(..))", throwing = "throwable")public void afterThrowing(JoinPoint joinPoint, Throwable throwable) {}切点表达式:固定语法:execution(1 2 3.4.5(6))1:访问修饰符,public / privae2:方法的返回参数类型,String / int / void如果不考虑访问修饰符 和 返回值类型的话,这两位整合在一起,写成*这两位是一体的,如果不考虑就都不考虑,不能出现 * String 这种情况3:包的位置具体包:com.atguigu.service.impl单层模糊:com.atguigu.service.*多层模糊:com..impl记住,..不能开头哦例如:找出所有impl包:com..impl,不能写成..impl,能写成 *..impl4:类的名称具体:myCLass模糊:*部分模糊:*Impl,意思是类名以Impl结尾的5:方法名语法和 上面4类的名称一样6:形参列表没有参数:()有具体的参数:(String)、(String,int)模糊参数:(..),意思是有没有参数都行,有多少个参数都行部分模糊:(String..),意思是String后面有没有无所谓(..int),意思是,最后一个参数是int(String..int),意思是,第一个参数是String,最后一个是int,中间的无所谓说一下切点表达式的提取和复用方式1、在当前类中提取首先,定义一个public void xxx(){} 这样的空方法然后,用注解@Pointcut("execution(* com..impl.*.*(..))")最后,增强注解中,引用上面定义的xxx这个空方法即可方式2、创建一个专门存储切点表达式的Xxx类只不过使用的时候,要这样:Xxx类的权限定符.方法名()如果,有多个增强类,优先使用哪一个?这就要用到:@Order(10),指定一个优先级的值,值越小,优先级越高,越高的前置先执行,后置后执行给增强类加上@Order(10)这个注解,就能控制这些增强类的优先级了@Component
@Aspect
@Order(10)
public class MyAdvice {切点表达式的提取和复用 - 方式1、在当前类中提取@Pointcut("execution(* com..impl.*.*(..))")public void pc(){}@Before("execution(* com..impl.*.*(..))")public void before(JoinPoint joinPoint) {获取方法属于的类的信息String simpleName = joinPoint.getTarget().getClass().getSimpleName();System.out.println("simpleName=" + simpleName);获取访问修饰符int modifiers = joinPoint.getSignature().getModifiers();String s = Modifier.toString(modifiers);获取方法名String name = joinPoint.getSignature().getName();System.out.println("name= " + name);获取目标方法的参数列表(就是获取目标方法的参数)Object[] args = joinPoint.getArgs();}@AfterReturning(value = "execution(* com..impl.*.*(..))", returning = "ret")public void afterReturning(JoinPoint joinPoint, Object ret) {}// @AfterThrowing(value = "execution(* com..impl.*.*(..))", throwing = "throwable")@AfterThrowing(value = "com.atguigu.pointcut.MyPointCut.myPc()", throwing = "throwable")public void afterThrowing(JoinPoint joinPoint, Throwable throwable) {}// @After("execution(* com..impl.*.*(..))") 未使用 “切点表达式的提取和复用” 之前@After("pc()") // 使用 “切点表达式的提取和复用” 之后public void after(JoinPoint joinPoint) {}
}
最后,写一个测试类
src/text/java/com.atguigu.test/SpringAopTest.java
package com.atguigu.test;import com.atguigu.config.JavaConfig;
import com.atguigu.service.Calculator;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;@SpringJUnitConfig(value = JavaConfig.class)
public class SpringAopTest {@Autowiredprivate Calculator calculator;@Testpublic void test() {int add = calculator.add(1, 1);System.out.println("add= " + add);}
}