AOP相关的重要概念

  • Aspect(切面)
    • Aspect声明类似于java的类声明,在Aspect中包含一些Pointcut和相应的Advice
  • Joint point(连接点)
    • 表示在程序中明确定义的点,典型的包括方法调用,对类成员的访问以及异常处理程序块的执行等,它自身还可以嵌套其他的joint point
  • Pointcut(切点)
    • 表示一组joint point,这些连接点或是通过逻辑关系组合起来,或是通过统配、正则表达式等方式集中起来,它定义了相应的Advice将要发生的地方。
  • Target(目标对象)
    • 织入Advice的目标对象
  • Weaving(织入)
    • 将Aspect和其他对象连接起来,并且创建Adviced object的过程

      AOP注解实现案例

  1. 定义一个config类(配置类),相当于一个applicationContext.xml文件,用于配置注解扫描包等
  2. 定义切面类,增强方法,实现AOP
  3. 定义目标类和目标方法
  4. 测试

AspectJ是一个专门用于实现Spring的AOP的框架,比Spring自带的AOP工具更强大、更好用,所以普遍使用AspectJ。先加入依赖:

  1. <dependency>
  2. <groupId>org.springframework</groupId>
  3. <artifactId>spring-context</artifactId>
  4. <version>5.2.9.RELEASE</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.springframework</groupId>
  8. <artifactId>spring-aspects</artifactId>
  9. <version>5.2.9.RELEASE</version>
  10. </dependency>
package com.quail.config;

import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

/**
 * @author quail
 * @date 2021/3/19 18:18
 * @TODO 定义配置类,用于告诉spring我们使用注解方式
 */
@Configurable//表示这个是一个配置类
@ComponentScan("com.quail")//表示扫描包
@EnableAspectJAutoProxy//开启Aspectj的自动代理
public class AppConfig {
}
package com.quail.aspects;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
 * @author quail
 * @date 2021/3/19 18:23
 * @TODO 用注解方式实现切面
 */
@Component//将该类交给spring管理
@Aspect//表示这是一个切面类
public class AspectsAnnotation {

    // 定义切点描述,这个方法的名字就是引用这个切点
    @Pointcut("execution(* com.quail.dao..*.*(..))")
    public void daoPointCut(){}

    //前置通知
    @Before("args(name) && daoPointCut()")//值是切点描述
    public void before(JoinPoint joinPoint,String name){
        System.out.println("--前置通知--"+name);
    }

    @After("daoPointCut()")
    public void After(){
        System.out.println("最终通知");
    }

    @Around("daoPointCut()")
    public Object around(ProceedingJoinPoint joinPoint){
        System.out.println("--环绕通知的前置通知--");
        // 目标方法
        Object proceed = null;
        try {
            proceed = joinPoint.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        System.out.println("--环绕通知的后置通知--");
        return proceed;
    }

    @AfterReturning(value = "daoPointCut()",returning = "valueResult")
    public void afterReturning(int valueResult){
        System.out.println("--后置通知--");
        System.out.println("--目标方法的返回值--"+valueResult);
    }
}
@Component//表示将这个类交给spring管理,创建这个类的bean
public class UserDaoImpl implements UserDao {
    public int save(String name) {
        System.out.println("我的名字是:"+name);
        return 1;
    }
}
public class AspectsTest {
    @Test
    public void test(){
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
        ctx.register(AppConfig.class);//注册配置类,必须
        ctx.refresh();//刷新容器,必须
        UserDao userDao = ctx.getBean(UserDao.class);
        userDao.save("quail");
    }
}

执行结果:image.png