AOP:【动态代理】
指在程序的运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式
1、导入aop模块:spring-aop(spring-aspect)
2、定义一个业务逻辑类(MathCalculator),在业务逻辑进行的时候进行日志打印( 方法运行之前,方法运行之后,方法返回,xxx)
3、定义一个切面类LogAspect,切面类的方法需要动态感知MathCalculator.div运行到哪一步再通知执行
通知方法:
1)、@Before 前置通知:logStart,在目标方法(div)运行之前执行
2)、@After 后置通知:logEnd, 在目标方法(div)结束后执行(在正常结束或者异常结束的时候都可运行)
3)、@AfterReturning 返回通知:logReturn, 在目标方法(div)正常返回的时候执行
4)、@AfterThrowing 异常通知:logException, 在目标方法(div)出现异常后执行
5)、@Around 环绕通知:动态代理,手动推进方法运行(JoinPoint.proced())
4、给切面类的目标方法标注何时何地运行(通知注解)
5、将切面类和目标逻辑类(目标方法所在类)都加入到容器中
6、必须告诉spring哪个是切面类(加入切面类的注解:@Aspect)
[7]、给配置类中加入@EnableAspectJAutoProxy【开启基于注解的AOP模式】
三步:
1、将业务逻辑类和切面类都加入到spring容器中,并告诉spring哪个是切面类(@Aspect)
2、在切面类的通知方法上标注通知注解,告诉spring何时何地运行(切入点表达式)
3、开启基于注解的aop模式,@EnableAspectJAutoProxy
代码示例如下:
1、逻辑类
package com.imooc.lamelbdatest.lambdatest.aop;
public class MathCalculator {
public int div(int k, int v) {
System.out.println("MathCalculator.div......");
return k/v;
}
}
2、切面类
package com.imooc.lamelbdatest.lambdatest.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import java.util.Arrays;
/**
* 切入类
* @Aspect 告诉spring哪个是切面类
*
*/
@Aspect
public class LogAspect {
/**
* 抽取公共的切入点表达式
* 1、本类引用
* 2、其他类引用
*/
@Pointcut("execution(public int com.imooc.lamelbdatest.lambdatest.aop.MathCalculator.*(..))")
public void pointCut() { }
/**
* @Before 在目标方法执行之前切入,切入点表达式(指定在哪个方法切入)
*/
@Before(value = "pointCut()")
public void logStart(JoinPoint joinPoint) {
Object[] args = joinPoint.getArgs();
System.out.println(joinPoint.getSignature().getName()+"除法运行。。。@Before:参数为{"+ Arrays.asList(args) +"}");
}
@After(value = "com.imooc.lamelbdatest.lambdatest.aop.LogAspect.pointCut()")
public void logEnd(JoinPoint joinPoint) {
System.out.println(joinPoint.getSignature().getName()+"除法结束。。。@After:参数为{}");
}
// JoinPoint一定要出现在参数表前面
@AfterReturning(value = "pointCut()", returning = "result")
public void logReturn(JoinPoint joinPoint, Object result) {
System.out.println(joinPoint.getSignature().getName()+"除法返回。。。@AfterReturning:参数为{"+result+"}");
}
@AfterThrowing(value = "pointCut()", throwing = "e")
public void logException(JoinPoint joinPoint, Exception e) {
System.out.println(joinPoint.getSignature().getName()+"除法异常。。。@AfterThrowing:参数为{"+e+"}");
}
}
3、config类
@EnableAspectJAutoProxy
@Configuration
public class MainConfigOfAOP {
// 目标逻辑类加入容器
@Bean
public MathCalculator mathCalculator() {
return new MathCalculator();
}
// 切面类加入容器
@Bean
public LogAspect logAspect() {
return new LogAspect();
}
}
4、测试类
public class IOCTest_AOP {
@Test
public void test1() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAOP.class);
MathCalculator bean = applicationContext.getBean(MathCalculator.class);
int div = bean.div(1, 1);
System.out.println(div);
applicationContext.close();
}
}