第二部分:AOP

一、AOP简介

AOP(Aspect Oriented Programming)面向切面编程,一种编程范式,指导开发者如何组织程序结构。

AOP是OOP(面向对象编程)的进阶版。

作用:在不改变原始设计的基础上为其进行功能增强。

spring理念:无侵入式。

第二部分:AOP_第1张图片

第二部分:AOP_第2张图片

 二、AOP入门实例

1、pom.xml导入坐标:注解开发(spring-context)、切面编程(aspectjweaver)

2、配置类SpringConfig 内添加注解@EnableAspectJAutoProxy                                                   (开启spring对AOP注解驱动支持)表示要注解开发AOP

3、通知类MyAdvice:定义通知(功能)、定义切入点(位置)定义切面(绑定通知和切入点)

@Component //定义通知类受spring容器管理(让spring加载此通知类)
@Aspect //定义当前类为切面类(让spring明白此类 是做AOP的)

//在此类定义通知(共性功能)
public class MyAdvice {
    //定义切入点(本质上就是确定要加功能的方法的准确位置)(
    // 依托一个不具有实际意义的方法进行,即无参无返回值,方法体无实际逻辑)
    @Pointcut("execution(void com.itheima.dao.BookDao.update())")
    private void pt(){}

    //将切入点(位置)和通知(功能)绑定
    @Before("pt()")

    //定义通知(本质就是要添加的功能)
    public void method(){
        System.out.println(System.currentTimeMillis());
    }
}

三、AOP工作流程

springAOP本质:代理模式           

如果切入点能和我要造bean的那个类匹配上对应的方法,则造代理对象;否则造原始对象

打印对象的getClass()方法(如bookDao.getClass())就可以看见是代理对象还是原始对象

第二部分:AOP_第3张图片

第二部分:AOP_第4张图片

四、AOP切入点表达式

切入点定位到接口 & 实现类均可(但是写到实现类就紧耦合了,所以不写)

@Pointcut("execution(void com.itheima.BookDao.updata())")
@Pointcut("execution(void com.itheima.dao.impl.BookDaoImpl.updata())")

1、语法格式:

第二部分:AOP_第5张图片

 2、通配符第二部分:AOP_第6张图片

 3、书写技巧

第二部分:AOP_第7张图片

 五、AOP通知类型<5>

                               AOP通知共分为5种类型:

前置通知、后置通知、环绕通知(重点)、返回后通知(了解)、抛出异常后通知(了解)

注意:环绕通知对原始方法调用以后,原始方法的返回值可以接出来,最终还要手动给送回去。下文中环绕通知即为规范格式。

@Component //定义通知类受spring容器管理(让spring加载此通知类)
@Aspect //定义当前类为切面类(让spring明白此类 是做AOP的)

//在此类定义通知(共性功能)
public class MyAdvice {
    //定义切入点(本质上就是确定要加功能的方法的准确位置)(
    // 依托一个不具有实际意义的方法进行,即无参无返回值,方法体无实际逻辑)
    @Pointcut("execution(void com.itheima.dao.BookDao.update())")
    public void pt1(){}

    @Pointcut("execution(int com.itheima.dao.BookDao.select())")
    public void pt2(){}

    //将切入点(位置)和通知(功能)绑定
    @Before("pt1()")//前置通知
    public void before(){
        System.out.println("此处是增强添加的通知,并且是一个前置通知");
    }
    @After("pt1()")//后置通知
    public void after(){
        System.out.println("此处是增强添加的通知,并且是一个后置通知");
    }

    @Around("pt1()")//环绕通知
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("此处是增强添加的通知,并且是一个环绕通知");
        Object ret = pjp.proceed();
        System.out.println("此处是增强添加的通知,并且是一个环绕通知");
        return ret;
    }

剩下俩个为:
@AfterReturning("")
@AfterThrowing("")

第二部分:AOP_第8张图片

 此处可以利用around对原始方法进行《隔离》!

第二部分:AOP_第9张图片

六、万次执行效率测试

测试业务层:

切入点表达式要确定业务层

@Pointcut("execution(* com.itheima.dao.*.*())")
    public void pt1(){}

采用环绕通知获取执行万次的前后系统时间

 @Around("pt1()")
    public void method(ProceedingJoinPoint pjp) throws Throwable {
        //获取执行签名信息
        Signature signature = pjp.getSignature();
        //通过签名获取接口名
        String className = signature.getDeclaringTypeName();
        //通过签名获取方法名
        String methodName = signature.getName();

        long start = (int) System.currentTimeMillis();
        for(int i = 0; i < 10000;i++){
            pjp.proceed();//此处代表执行业务层一万次
        }
        long end = (int) System.currentTimeMillis();
        System.out.println("执行一万次" + className + "." + methodName +"--->" + (end - start) + "ms");

    }

七、AOP通知获取数据

AOP是对原始方法进行增强的,必然要知道原始方法的数据。

基本操作:在通知的方法的参数内加上接口,调用接口的方法来获取原始方法的参数。

获取的数据有三类:原始操作的参数、原始操作的返回值、原始操作的异常。

每种类型的数据只有五类通知的部分可以获取:

第二部分:AOP_第10张图片

1、获取参数

获取的参数类型为数组;对于前置通知获取参数后,可以对数据检验错误、修改等操作。

 //将切入点(位置)和通知(功能)绑定
    //@Before("pt1()")//前置通知
    public void before(JoinPoint jp){
        System.out.println("此处是增强添加的通知,并且是一个前置通知");
        Object[] args = jp.getArgs();//此方法getargs获取参数是数组类型
        System.out.println(Arrays.toString(args));
    }
后置、环绕、、都一样。

2、获取返回值

@Around("pt1()")//环绕通知
public Object around(ProceedingJoinPoint pjp) throws Throwable {
    Object args[] = pjp.getArgs();
    return ret;

3、获取异常信息

    @AfterThrowing(value = "pt1",throwing = "t")
    public void afterThrowing(Throwable t){
        System.out.println("返回异常" + t);
    }
    //注意通知的方法的参数要和标签的参数一致

第二部分:AOP_第11张图片

八、百度网盘粘贴:字符串匹配自动处理多余的空格

AOP增强

@Component
@Aspect
public class DataAdvice {
    //定义切入点
    @Pointcut("execution(boolean com.itheima.service.ResourcesService.openURL(..))")
    public void pt(){}

    @Around("pt()")
    public Object trimStr(ProceedingJoinPoint pjp) throws  Throwable{
        //提前获取参数 将参数修改后在传参给原始方法内
        Object args[] = pjp.getArgs();
        for (int i = 0; i < args.length; i++) {
            if(args[i].getClass().equals(String.class)){//判断是不是字符串类型
                args[i] = args[i].toString().trim(); //是字符串类型就trim
            }
        }
        Object ret = pjp.proceed(args);//将空格处理后的参数在传参给要执行的原始方法
        return ret;
    }
}

十一、AOP总结

回忆。

要会啥呢?

1、得知道pom.xml文件里面要配置spring-context依赖(spring注解开发)、aspectjweaver依赖(AOP注解和切入点表达式,AOP核心功能已经被加载到spring-context依赖了)

2、知道要在spring核心配置类中加载AOP

3、得知道在AOP配置类中加载扫描啥的 切入点表达式会写。@Pointcut(“”execution())

4、环绕通知@Around(“”)参数ProceedingJoinpoint pjp

要写固定的执行原始方法得到返回值Object ret = pjp.proceed(args); return ret;

以上这些都是固定的。

5、根据不同的需要,通知类里面的方法咋写就看自己的了。

你可能感兴趣的:(Spring,java,开发语言)