设为首页 加入收藏

TOP

day10-AOP-03(一)
2023-07-25 21:42:55 】 浏览:78
Tags:day10-AOP-03

AOP-03

7.AOP-切入表达式

7.1切入表达式的具体使用

1.切入表达式的作用:

通过表达式的方式定义一个或多个具体的连接点。

2.语法细节:

(1)切入表达式的语法格式:

execution([权限修饰符] [返回值类型] [简单类名/全类名] [方法名]([参数列表])

若目标类、接口与该切面类在用同一个包中,可以省略包名,只写简单类名


(2)举例说明:

例子1:

表达式:execution(* com.sina.spring.ArithmeticCalculator.*(..))

含义:ArithmeticCalculator.* :接口中声明的所有方法。第一个 * 代表任意修饰符和任意返回值。 第二个 * 代表任意方法。.. 代表匹配任意数量和任意类型的参数,若目标类、接口与该切面类在用同一个包中,可以省略包名。

例子2:

表达式:execution(public * ArithmeticCalculator.*(..))

含义:ArithmeticCalculator 接口中的所有公有方法

例子3:

表达式:execution(public double ArithmeticCalculator.*(..))

含义:ArithmeticCalculator 接口中返回 double 类型数值的方法

例子4:

表达式:execution(public double ArithmeticCalculator.*(double, ..))

含义:第一个参数为double 类型的方法。.. 匹配任意数量、任意类型的参数。

例子5:

表达式:execution(public double ArithmeticCalculator.*(double, double))

含义:参数类型为double ,double 类型的方法。


(3)在AspectJ中,切入点表达式可以通过 && 或者 || 或者 ! 等操作符结合起来

例子:

表达式:execution(* *.add(int, ..))|| exexution(* *.sub(int, ..))

含义:任意类中第一个参数为 int 类型的 add 方法或 sub 方法

7.2注意事项和细节

  1. 切入表达式可以指向(实现了接口的)类的方法,这时切入表达式会对该类/对象生效

  2. 切入表达式也可以指向接口的方法,这时切入表达式会对实现了接口的类/对象生效

  3. 切入表达式可以对没有实现接口的类进行切入。

    这涉及到CGlib动态代理:动态代理jdk的Proxy与spring的CGlib

  4. 两个动态代理的区别:

    • JDK动态代理是面向接口的,只能增强实现类中接口中存在的方法。CGlib是面向父类的,可以增强父类的所有方法

    • JDK得到的对象是JDK代理对象实例,而CGlib得到的对象是被代理对象的子类

静态代理例子:

一个普通类Car:

package com.li.aop.hw;

import org.springframework.stereotype.Component;

/**
 * @author 李
 * @version 1.0
 */
@Component
public class Car {
    public void run() {
        System.out.println("小汽车在running...");
    }
}

MyAspect切面类:

package com.li.aop.hw;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * @author 李
 * @version 1.0
 * 切面类
 */

@Component
@Aspect
public class MyAspect {
    //CGlib
    //给没有实现接口的一个普通类设置前置通知,其他通知亦可以设置
    @Before(value = "execution(public void Car.run())")
    public void ok(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("MyAspect前置通知ok()-目标方法-" + methodName +
                " 参数-" + Arrays.toString(joinPoint.getArgs()));
    }
}

测试类:

package com.li.aop.hw;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.testng.annotations.Test;

/**
 * @author 李
 * @version 1.0
 */
public class UsbTest {
    @Test
    public void UsbAspectTest() {
        ApplicationContext ioc = new ClassPathXmlApplicationContext("beans08.xml");
        //carProxy是 被代理对象的子类
        Car carProxy = ioc.getBean(Car.class);
        System.out.println("carProxy的实际运行类型=" + carProxy.getClass());
        carProxy.run();
    }
}

测试结果:

image-20230125221222962

8.AOP-JoinPoint

在切面类的通知方法中,可以通过 JoinPoint对象获取到目标方法的一系列信息:

JoinPoint对象的方法 释义
getSignature().getName() 获取目标方法名
getSignature().getDeclaringType().getSimpleName() 获取目标方法所属类的简单类名
getSignature().getDeclaringTypeName() 获取目标方法所属类的全类名
getSignature().getModifiers() 获取目标方法声明类型(public/private/protected)
getArgs() 获取传入目标方法的参数,返回一个数组
getTarget() 获取被代理的对象
getThis() 获取代理对象自己

9.AOP-返回通知获取结果

  • 在返回通知 @AfterReturning 中,可以获取目标方法返回的结果。

我们在 @AfterReturning (返回通知)的注解源码中可以看到有一个returnin

首页 上一页 1 2 3 4 5 6 7 下一页 尾页 1/7/7
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇学习笔记——Linux中搜索查找类命.. 下一篇读Java8函数式编程笔记02_流

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目