1.简介
Spring AOP是Spring针对面向切面编程的落地方案,用于解决非核心代码的冗余问题。
Spring AOP只能运用于存于IoC容器中的对象。
2.知识
2.1 底层实现
Spring AOP框架针对不同情况有两种底层实现基于Jdk的动态代理和基于cglib:
- 动态代理:用于有接口的类,采用继承接口的方式实现代理。
- cglib:用于没有接口的类,采用继承子类的方式实现代理。
2.2 插入点
Spring AOP框架总共有5种插入点:
- 前置通知@Before: 目标函数执行前执行
- 返回通知@AfterReturning:目标函数执行后执行
- 异常通知@AfterThrowing:catch中执行
- 后置通知@After:finally中执行
- 环绕通知@Around:包含上面所有通知节点,完全自定义
3.代码
要使用Spring AOP,必须加入以下组件到pom.xml中
xml
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>6.0.6</version>
</dependency>
配置类中开启AOP
java
@Configuration//声明这是一个配置类
@ComponentScan("com.jojo")//设置扫描范围
@EnableAspectJAutoProxy//开启AOP
public class JavaConfig {
}
切面增强类的编写:
java
@Component//增强类必须放入IoC容器
@Aspect//声明切面
@Order(2)//设置优先级,值越小,优先级越高,前置先执行,后置后执行
public class LogAdvice {
@Before("com.jojo.pointcut.MyPointCut.point()")
public void before(JoinPoint joinPoint){//目标方法的封装对象
//1.获取的类名
String simpleName = joinPoint.getTarget().getClass().getSimpleName();
//2.获取方法名称
int modifiers = joinPoint.getSignature().getModifiers();
String s = Modifier.toString(modifiers);//获取是public还是其他
String name = joinPoint.getSignature().getName();//获取方法名
//3.获取参数列表
Object[] args = joinPoint.getArgs();//获取参数
}
@AfterReturning(value = "com.jojo.pointcut.MyPointCut.point()",returning = "result")//接受核心函数返回变量到result
public void afterReturning(JoinPoint joinPoint, Object result){//设置返回变量
}
@After("com.jojo.pointcut.MyPointCut.point()")
public void after(JoinPoint joinPoint){
}
@AfterThrowing(value = "execution(* com..impl.*.*(..))",throwing = "throwable")//接受异常信息到throwable
public void afterThrowing(JoinPoint joinPoint,Throwable throwable){//设置异常信息变量
}
@Around("com.jojo.pointcut.MyPointCut.point()")//声明环绕通知
public Object transaction(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("前置通知");//增强代码,前置通知
Object[] args = joinPoint.getArgs();//目标参数获取
System.out.println("返回通知");//增强代码,返回通知
Object result = null;
try {
result = joinPoint.proceed(args);//目标函数调用
} catch (Throwable e){
System.out.println("异常通知");//增强代码,异常通知
throw new RuntimeException(e);//抛出异常
} finally{
System.out.println("后置通知");//增强代码,后置通知
}
return result;//目标方法的返回值
}
}
插入点类的编写
java
@Component
public class MyPointCut {
@Pointcut("execution(* com.jojo.service.impl.*.*(..))")//插入点统一管理
public void point(){}
}
测试:
java
@SpringJUnitConfig(value = JavaConfig.class)//声明使用的配置类
public class SpringAopTest {
@Autowired
//针对有接口类必须使用接口而非接口实现类来声明
//针对无接口类使用实现类来声明
private MyTest myTest;
@Test
public void test(){
int result = myTest.do(1);
System.out.println("result = "+ result);
}
}