JavaEE_10_SpringAOP

《SpringAOP》

目录

  • 代理模式(掌握)
  • SpringAOP简介(熟练)
  • SpringAOP使用(掌握)
  • 参数传递(掌握)

一、代理模式

为其他对象提供一种代理,从而实现对这个对象的访问控制。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

设计模式中有一个设计原则是开闭原则,它是Java世界里最基础的设计原则,开闭原则明确要求软件应该实现对扩展开放,对修改关闭

请添加图片描述

二、SpringAOP简介

AOP(面向切面编程)是对传统OOP(面向对象编程)一种补充和完善,OOP引入封装、继承、多态等概念来建立一种对象层次结构,用于模拟公共行为的一个集合。不过OOP允许开发者定义纵向的关系,但并不适合定义横向的关系,例如日志功能。

AOP并不是Spring框架独有的,不同框架都有对AOP的支持,并各自有特点,所以这里需要再次强调一下,SpringAOP是一种基于方法拦截的AOP,即SpringAOP只支持对方法拦截

请添加图片描述

三、SpringAOP使用

操作术语

  1. 横切关注点

对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点;

  1. 切面(aspect)

OOP中类是对物体特征的抽象,那么切面就是AOP中对横切关注点的抽象,切面通常是一个类,里面可以定义切入点和通知。

  1. 连接点(joinpoint)

被拦截到的点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器

  1. 切入点(pointcut)

对连接点进行拦截的定义,通过书写切入点表达式决定究竟要把哪些方法给拦截下来。

  1. 通知(advice)

所谓通知指的就是指拦截到连接点之后要执行的代码,一般来说就是对目标方法的增强,通知分为前置(在目标方法前执行)、后置(在目标方法后执行)、异常(在目标方法抛出异常后执行)、返回(在目标方法返回结果后执行)、环绕(可以同时实现前置和后置功能)通知五种类型。

execution正则表达式

execution( aop.TestService.ptrint(…))*

  1. execution:表示执行对应方法的时候会触发;
  2. *:代表任意类型返回类型的方法;
  3. aop.TestService:代表类的全限定名;
  4. ptrint:代表被拦截的方法名字;
  5. (…):代表任意的参数。

案例一

  1. pom.xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
  1. com.hpr.aop.AopTest
package com.hpr.aop;

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

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;

//@Aspect表示当前类是一个切面
@Aspect
@Component
public class AopTest {

    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    //切入点
    @Pointcut("execution(* com.hpr.service.impl.TeacherService.insert(..))")
    public void pointcut() {
    }

    //返回通知(返回结果后)
    @AfterReturning(pointcut = "pointcut()")
    public void afterReturning() {
        File logDir = new File("./logs");
        if (!logDir.exists()) {
            logDir.mkdir();
        }
        try {
            FileWriter fw = new FileWriter("./logs/insert.log", true);
            PrintWriter pw = new PrintWriter(fw);
            pw.println("【" + sdf.format(new Date()) + "】:teacher信息新增成功!");
            pw.close();
            fw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //前置通知(方法执行前)
//    @Before("pointcut()")
//    public void before() {
//    }

    //后置通知(方法执行后)
//    @After("pointcut()")
//    public void after() {
//
//    }

    //环绕通知
//    @Around("pointcut()")
//    public void around(ProceedingJoinPoint pj) {
//    }

    //异常通知(发生异常后)
//    @AfterThrowing(pointcut = "pointcut()", throwing = "e")
//    public void afterTrowing(Throwable e) {
//    }
}
  1. 启动测试

请添加图片描述

执行结果

  • /logs/insert.log

请添加图片描述

四、参数传递

使用SpringAOP时,想要获取所拦截方法传入的参数及返回的结果,可进行以下操作。

  1. 修改切面
...
public class AopTest {
    ...
    //切入点
    @Pointcut("execution(* com.hpr.service.impl.TeacherService.insert(..))&&args(teacher)")
    public void pointcut(Teacher teacher) {
    }

    //返回通知(返回结果后)
    @AfterReturning(pointcut = "pointcut(teacher)", returning = "response")
    public void afterReturning(Response<Teacher> response, Teacher teacher) {
        File logDir = new File("./logs");
        if (!logDir.exists()) {
            logDir.mkdir();
        }
        try {
            FileWriter fw = new FileWriter("./logs/insert.log", true);
            PrintWriter pw = new PrintWriter(fw);
            pw.println("【" + sdf.format(new Date()) + "】:teacher信息新增成功!");
            pw.println(response.getData());
            pw.close();
            fw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    ...
}
  1. 启动测试

请添加图片描述

执行结果

  • /logs/insert.log

请添加图片描述

总结

重点

  1. 代理模式及开闭原则;
  2. SpringAOP相关术语;
  3. SpringAOP代码实现;
  4. SpringAOP方法参数及返回结果获取。

难点

  1. SpringAOP代码实现;
  2. SpringAOP方法参数及返回结果获取。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值