AOP:在程序运行期间将某段代码切入到指定方法指定位置进行运行的编程方式
AOP中相关概念
- Aspect(切面): Aspect 声明类似于 Java 中的类声明,在 Aspect 中会包含着一些 Pointcut 以及相应的Advice。
- Jointpoint(连接点):表示在程序中明确定义的点,典型的包括方法调用,对类成员的访问以及异常处理程序块的执行等等,它自身还可以嵌套其它joint point。
- Pointcut(切点):表示一组 joint point,这些 joint point
或是通过逻辑关系组合起来,或是通过通配、正则表达式等方式集中起来,它定义了相应的 Advice 将要发生的地方。 - Advice(增强):Advice 定义了在 Pointcut 里面定义的程序点具体要做的操作,它通过 before、after 和 around 来区别是在每个 joint point 之前、之后还是代替执行的代码。
- Target(目标对象):织入 Advice的目标对象.。
- Weaving(织入):将 Aspect 和其他对象连接起来, 并创建 Adviced object 的过程
在AOP中切面就是与业务逻辑独立,但又垂直存在于业务逻辑的代码结构中的通用功能组合;切面与业务逻辑相交的点就是切点,在切点上可以把要完成增强操作的目标对象(Target)连接到切面里,这个连接的方式就叫织入。连接点就是把业务逻辑离散化后的关键节点;Advice(增强)就是切面在切点上要执行的功能增加的具体操作。
基于注解方式的AOP
- 给切面类的目标方法标注通知注解
- 将切面类和业务逻辑类都加入容器中
- 必须告诉spring哪个是切面类:给切面类上加一个注解–>@Aspect
- 在切面类上的每一个通知方法都标注对应的通知注解,告诉Spring何时何地切入运行
- 需要给配置类加@EnableAspectJAutoProxy(开启基于注解的AOP模式)
代码实现
配置类
@EnableAspectJAutoProxy //开启AOP功能
@Configuration
public class MainConfigOfAOP {
@Bean
//业务逻辑类加入到容器中
public MathCalculator mathCalculator(){
return new MathCalculator();
}
@Bean
public LogAspect aspect(){
return new LogAspect();
}
}
业务逻辑类
public class MathCalculator { //在业务逻辑运行的时候将日志进行打印,方法之前,运行,异常
public int div(int i,int j){
try {
return i/j;
} catch (Exception e) {
System.out.println("除数不能为0!");
}
return -1;
}
}
切面类
@Aspect //告诉Spring当前是一个切面类
public class LogAspect {
//抽取公共的切入点表达式
//1.本类引用
//2.其他的切面引用
@Pointcut("execution (public int test.aop.MathCalculator.div(int,int))")
public void pointCut() {
}
// 在目标方法之前切入:切入点表达式(指定在哪个方法切入)
@Before("pointCut()")
public void logStart(JoinPoint joinPoint) {
System.out.println("除法运行..."+joinPoint.getSignature().getName()+"运行:"+ Arrays.asList(joinPoint.getArgs()));
}
@After("test.aop.LogAspect.pointCut()")
public void logEnd() {
System.out.println("除法结束...");
}
@AfterReturning(value="pointCut()",returning = "result")
public void logReturn(Object result) {
System.out.println("返回计算结果:"+result);
}
@AfterThrowing(value = "pointCut()",throwing = "exception")
public void logException(Exception exception) {
System.out.println("除法异常:"+exception);
}
}
测试类
@Test
public void testAOP() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAOP.class);
MathCalculator calculator = applicationContext.getBean(MathCalculator.class);
calculator.div(1, 0);
applicationContext.close();
}