视频地址:https://www.bilibili.com/video/BV1oW41167AV
对应代码Git库地址:https://github.com/whh306318848/spring-annotation.git
- AOP【动态代理】:指在程序运行期间,动态的将某段代码切入到指定方法指定位置进行运行的变成方式
- 使用AOP步骤:
2.1. 在pom文件中导入AOP模块,String AOP模块做了一些简化,只需要配置几个注解就可以运行起来
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.2.12.RELEASE</version>
</dependency>
2.2. 定义业务逻辑类MathCalculator,在业务逻辑运行的时候将日志进行打印(方法运行之前、方法运行结束、方法出现异常等情况)
public class MathCalculator {
public int div(int i, int j) {
return i / j;
}
}
2.3. 定义一个日志切面类LogAspects,切面类里面的方法需要动态感知MathCalculator.div运行到哪里进行执行
public class LogAspects {
public void logStart() {
System.out.println("除法运行...参数列表是:{}");
}
public void logEnd() {
System.out.println("除法结束...");
}
public void logReturn() {
System.out.println("除法正常返回...运行结果:{}");
}
public void logException() {
System.out.println("除法异常...异常信息:{}");
}
}
通知方法类型:
– 前置通知(@Before):相当于logStart,在目标方法运行之前运行
– 后置通知(@After):相当于logEnd,在目标方法运行结束之后运行(无论方法正常结束还是异常结束都调用)
– 返回通知(@AfterReturning):相当于logReturn,在目标方法正常返回之后运行
– 异常通知(@AfterThrowing):相当于logException,在目标方法运行出现异常以后运行
– 环绕通知(@Around):其是一个动态代理,可以手动推进目标方法运行(joinPoint.proceed()),是最底层的通知
2.4. 给切面类的目标方法标注何时何地运行(标志通知注解)
public class LogAspects {
// 抽取公共的切入点表达式
// 1、如果是本类引用,则@Pointcut的值不写任何内容
// 2、其他的切面引用,则@Pointcut要写execution(切入点表达式,即指定在哪个方法切入)
@Pointcut("execution(public int com.atguigu.aop.MathCalculator.*(..))")
public void pointCut() {}
// @Before注解是指在目标方法之前切入,其值是切入点表达式(指定在哪个方法切入)
@Before("public int com.atguigu.aop.MathCalculator.*(..)")
public void logStart() {
System.out.println("除法运行...参数列表是:{}");
}
// @After注解是指在目标方法运行结束之后切入
@After("pointCut()")
public void logEnd() {
System.out.println("除法结束...");
}
// @AfterReturning注解是指在目标方法正常返回之后切入
@AfterReturning("pointCut()")
public void logReturn() {
System.out.println("除法正常返回...运行结果:{}");
}
// @AfterThrowing注解是指在目标方法出现异常之后切入
@AfterThrowing("pointCut()")
public void logException() {
System.out.println("除法异常...异常信息:{}");
}
}
2.5. 将切面类和业务逻辑类(目标方法所在类)都加入到容器中
@Configuration
public class MainConfigOfAOP {
// 将业务逻辑类加入容器中
@Bean
public MathCalculator mathCalculator() {
return new MathCalculator();
}
// 将切面类加入容器中
@Bean
public LogAspects logAspects() {
return new LogAspects();
}
}
2.6. 必须告诉Sring哪个类是切面类,给切面类上加上@Aspect注解
@Aspect
public class LogAspects {
// ...
}
2.7. 给配置类上加@EnableAspectJAutoProxy注解,开启基于注解的AOP模式
@EnableAspectJAutoProxy
@Configuration
public class MainConfigOfAOP {
// ...
}
若是使用xml配置文件,则需要在xml配置文件中写入以下代码
<!-- 开启基于版的切面功能-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
2.8. 若想在使用Bean时触发AOP,不能使用自己在代码中创建的对象,需要使用Spring让其中的组件才能触发
2.9. 使用Spring AOP最重要三步总结:
– 将业务逻辑组件和切面类都加入到容器中,并告诉Spring哪个是切面类(@Aspect注解)
– 在切面类上的每一个通知方法上标注通知注解,告诉Spring何时何地运行(切入点表达式)
– 开启基于注解的AOP模式(@EnableAspectJAutoProxy注解)