SpringAOP使用方式

切点表达式

常用的符号:

*:匹配任何数量字符;

     ..:匹配任何数量字符的重复,如在类型模式中匹配任何数量子包;而在方法参数模式中匹配任何数量参数。

     +:匹配指定类型的子类型;仅能作为后缀放在类型模式后边。

一种常用的切点表达式如下:
(1):execution(* com.nuofankj.springdemo.aop.Service.(..)) (2):execution(* com.sample.service.impl..*.*(..))

(1)返回类型为任意类型,以Service开头的方法名,参数为任意参数;
(2)返回类型为任意类型,impl包及其子包(..)下的所有类的所有方法,任意参数类型;

基于切点表达式的使用方式
  • 1 可以通过在切点中配置,拿到入参信息
//切点方法为:
    @Override
    public String saveUser(String user,Integer age) {
        System.out.println("保存用户信息");
        if (Objects.equals(user,"e")){
            throw new RuntimeException();
        }
        return null;
    }
    /**切点配置为*/
    //方式一:通过pointcut方法中定义参数,拿到切点处的参数
    //通过Pointcut方法配置,拿到入参
    @Pointcut(value = "execution(* com.wht.springaop.USerService.saveUser(..)) && args(cat,dog)")
    public void pointcut2(String cat,Integer dog){
    };
    @Around("pointcut2(cat,dog)")
    public Object aroundExe(ProceedingJoinPoint joinPoint,String cat,Integer dog) throws Throwable {
        System.out.println("around1切面执行。。。");
        try {
            return joinPoint.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            throw  throwable;
        }finally {
            System.out.println("around2切面执行。。。");
        }
    }
  • 2 个人感觉最常用的还是这种,通过JoinPoint拿到入参信息
//通过JoinPoint拿到方法的入参信息
    @After("execution(* com.wht.springaop.USerService.testNormalAop(..))")
    public void AfterExe(JoinPoint point){
        Object[] args = point.getArgs();
        //参见JoinPoint的API介绍
        System.out.println("切点获取传入的参数为:"+ Arrays.asList(args));
        System.out.println("after:测试普通AOP方法");
    }
  • 3 另外可以通过自定义注解的方式使用,更加灵活
/**首先自定义注解*/
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface Log {
        String value() default "我是注解";
        // int key();
    }

    /**在要切入的方法上使用此注解*/
    @Log(value = "Log注解AOP")
    @Override
    public String testAnnotationAop(String name) {
        System.out.println("测试注解AOP方法");
        return "AOP注解方式";
    }

    /**配置切点,进行功能代码织入,同样有两种方式*/
    //【1】表示切点在Log注解标识的方法上,这种将Log写入参数中的形式能直接拿到Log注解信息
    @Pointcut(value = "@annotation(log)")
    public void pointcut(Log log){
    }
    @Around(value = "pointcut(log)")
    public Object get(ProceedingJoinPoint point,Log log) throws Throwable {
        System.out.println(log.value());//能拿到注解的值
        point.proceed();
        System.out.println("Around02注解AOP");//环绕通知
        return "123";
    }
    //【2】这种方式只能通过获取方法,然后获取方法上的注解的形式拿到,且@annotation需要配置注解的全限定名。
    @Before(value = "@annotation(com.wht.springaop.Log)")
    public void beforeExe(JoinPoint point){
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        //获取参数列表
        String[] names = signature.getParameterNames();
        //获取方法上的注解
        Log log = method.getAnnotation(Log.class);
        System.out.println("注解式拦截 " + log.value());
    }

配置切面时,不要忘记将切面类SpringBoot启动时注入为Bean实例,同时标记为切面类。即使用注解: @Aspect 和 @Component

JoinPoint切点的常用方法:
Signature getSignature(): 获取封装了署名信息的对象,在该对象中可以获取到目标方法名,所属类的Class等信息
Object[] getArgs(): 获取传入目标方法的参数对象   
Object getTarget(): 获取被代理的对象 
Object getThis():   获取代理对象  `