一、AOP
AOP:[动态代理]
指在程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式。
二、AOP 应用
1、导入 AOP 模块,Spring AOP:(spring-aspects)
2、定义一个业务逻辑类,在业务逻辑运行的时候将日志进行打印,在方法之前、方法运行结束、方法异常都有打印。
3、定义一个日志切面类,切面类里面的方法需要动态感知方法运行到哪里,然后执行
通知方法:
前置通知(@Before):在目标方法运行之前运行
后置通知(@After):在目标方法运行结束之后运行,无论正常结束还是异常结束
返回通知(@AfterReturning):在目标方法正常返回之后运行
异常通知(@AfterThrowing):在目标方法运行出现异常之后运行
环绕通知(@Around):动态代理,手动推进目标方法运行(joinPoint.procced())
4、给切面类的目标方法标注何时何地运行(通知注解)
5、将切面类和业务逻辑类(目标方法所在的类)都加入到容器中
6、必须告诉Spring哪个类是切面类(给切面类上加入一个注解)
7、给配置类中加@EnableAspectJAutoProxy,【开启基于注解的 aop 模式】(在Spring中很多的 @EnableXXX,开启某一功能)
三、AOP 案例
1、业务逻辑类
public class MathCalculator {
public int div(int i, int j) {
return i / j;
}
}
2、切面类
//@Aspect:告诉Spring,这个类是一个切面类
@Aspect
public class LogAspects {
//抽取公共的切入点表达式,execution 指定切入点表达式
//1、本类引用 @Before("pointCut()")
//2、其他的切面引入,引入全类名 @Before("com.njf.bean.LogAspects.pointCut()");
//切入点表达式与切入点方法不能同时出现
@Pointcut("execution(public int com.njf.bean.MathCalculator.div(int, int))")
public void pointCut() {
}
//@Before在目标方法之前切入;切入点表达式(指定在哪个方法切入)
//@Before("com.njf.bean.MathCalculator.*(..)") 所有的方法
//@Before("com.njf.bean.MathCalculator.div(int, int)") 指定的参数的方法
@Before("pointCut()")
public void logStart(JoinPoint joinPoint) {
Object[] args = joinPoint.getArgs();
System.out.println("@Before:" + joinPoint.getSignature().getName() + "方法运行了,参数列表是:" + Arrays.toString(args));
}
//@After("com.njf.bean.MathCalculator.div(int, int)")
@After("pointCut()")
public void logEnd(JoinPoint joinPoint) {
System.out.println("@After:" + joinPoint.getSignature().getName() + "方法结束了");
}
//JoinPoint 一定要出现在参数表的第一位
@AfterReturning(value = "pointCut()", returning = "result")
public void logReturn(JoinPoint joinPoint, Object result) {
System.out.println("@AfterReturning:" + joinPoint.getSignature().getName() + "方法正常返回,返回结果" + result);
}
@AfterThrowing(value = "com.njf.bean.LogAspects.pointCut()", throwing = "exception")
public void logException(JoinPoint joinPoint, Exception exception) {
System.out.println("@AfterThrowing:" + joinPoint.getSignature().getName() + "方法异常了,异常信息:" + exception);
}
}
3、配置类
@EnableAspectJAutoProxy //开启基于注解的 aop 模式
@Configuration
public class MainConfigOfAOP {
@Bean
public MathCalculator calculator() {
return new MathCalculator();
}
@Bean
public LogAspects logAspects() {
return new LogAspects();
}
}
四、小结
1、将业务逻辑组件和切面类都加入到容器中,告诉Spring那个是切面类(@Aspect)
2、在切面类上每一个通知方法标注通知注解,告诉Spring何时何地运行(切入点表达式)
3、开启基于注解的 aop模式