AOP概念 和 使用

目录

AOP的概念

什么是AOP?

什么是SpringAOP?

为什要⽤ AOP?

AOP的作用?

AOP的组成

通知

AOP的实现

1. 添加 Spring AOP 框架⽀持。

2. 定义切面和切点。

3. 定义通知。

切点表达式


AOP的概念

什么是AOP?

AOP(Aspect Oriented Programming):⾯向切⾯编程,它是⼀种思想,它是对某⼀类事情的 集中处理。

什么是SpringAOP?

⽽ AOP 是⼀种思想,⽽ Spring AOP 是⼀个框架,提供了⼀种对 AOP 思想的实现,它们的关系和 IoC 与 DI 类似。

为什要⽤ AOP?

在开发中,我们对于公共方法的处理分为三个阶段:

  1. 每个方法都去实现(初级)
  2. 抽取公共方法(中级)
  3. 采用AOP的方式,对代码进行无侵入是实现(高级)

因此,对于这种功能统⼀,且使⽤的地⽅较多的功能,在之前我们会抽取公共方法去实现,但是现在有更好的一个办法来处理这个问题,就是AOP。

也就是使⽤ AOP 可以扩充多个对象的某个能⼒,所以 AOP 可以说是 OOP(Object Oriented Programming,⾯向对象编程)的补充和完善。

AOP的作用?

提供声明式事务;允许用户自定义切面

AOP的组成

AOP由下边四部分组成:

切面(Aspect)

由切点(Pointcut)和通知(Advice)组成,既包含了横切逻辑的定义,也包含了连接点的定义。

连接点(Join Point)

应用执行过程中能够插入切面的一个点,这个点可以是方法调用时,抛出异常时,甚至修改字段时。切面代码可以利用这些点插入到应用的正常流程之中,并添加新的行为。

切点(Pointcut)

Pointcut的作用就是提供一组规则 来匹配Join Point,给满足规则的Join Point 添加Advice.

通知(Advice)

切面也有目标-他必须要完成的工作。在AOP中,切面的工作被称为通知。

那么是不是感觉难以理解呢?

不着急我们简单说一下, AOP使用来对某一类事情进行集中处理的,那么处理事情,这个整体就是一个切面,处理事情的范围就是切点,范围中具体的事物就是连接点,怎么处理就是通知。

简单的体系图如下:

AOP概念 和 使用_第1张图片

通知

通知又名拦截器,它定义了切面是做什么以及何时使用,即在某个特定的连接点上执行的动作,它是切面的具体实现。以目标方法为参照点,根据放置位置的地方不同,通知分为如下5种类型通知:

  • 前置通知使⽤ @Before:通知⽅法会在⽬标⽅法调⽤之前执⾏。
  • 后置通知使⽤ @After:通知⽅法会在⽬标⽅法返回或者抛出异常后调⽤。
  • 返回之后通知使⽤ @AfterReturning:通知⽅法会在⽬标⽅法返回后调⽤。
  • 抛异常后通知使⽤ @AfterThrowing:通知⽅法会在⽬标⽅法抛出异常后调⽤。
  • 环绕通知使⽤ @Around:通知包裹了被通知的⽅法,在被通知的⽅法通知之前和调⽤之后执⾏⾃定义的⾏为。

AOP的实现

实现步骤如下:

1. 添加 Spring AOP 框架⽀持。

2. 定义切⾯和切点。

3. 定义通知。

具体操作如下:

1. 添加 Spring AOP 框架⽀持。

首先我们建立一个新的Springboot项目,在配置文件中添加AOP框架:

 
            org.springframework.boot
            spring-boot-starter-aop
        

2. 定义切面和切点。

3. 定义通知。

定义一个切面:

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;
@Slf4j
@Component
@Aspect
public class LoginAspect {
//定义切点
    @Pointcut("execution(* com.example.springaopdemo.controller.UserController.*(..))")
    public void pointcut(){}
//定义通知
    @Before("pointcut()")
    public void before(){
        log.info("do before,,,,");
    }
    @After("pointcut()")
    public void after(){
        log.info("do after.....");
    }
    @AfterReturning("pointcut()")
    public void afterReturning(){
        log.info("do afterReturning....");
    }
    @AfterThrowing("pointcut()")
    public  void afterThrowing(){
        log.info("do afterThrowing....");
    }
//这里注意,环绕式通知必须自己写返回结果
    @Around("pointcut()")
    public Object around(ProceedingJoinPoint joinPoint){
        Object oj=null;
        log.info("之前");
        try{
            oj=joinPoint.proceed();//调用目标方法
        }catch(Throwable e){
            throw new RuntimeException(e);
        }
        log.info("之后");
        return oj;
    }

@Aspect是aop框架中提供的,表示是一个切面。切面类中最先定义的是切点,用@Pointcut注解表示是一个切点,括号里边是切点表达式。后边的是五大类型的通知。分别是用五大类名称进行注解。

切点表达式:

AspectJ ⽀持三种通配符

* 匹配任意字符,只匹配⼀个元素(包,类,或⽅法,⽅法参数)
.. 匹配任意字符,可以匹配多个元素 ,在表示类时,必须和 * 联合使⽤。
+ 表示按照类型匹配指定类的所有类,必须跟在类名后⾯,如 com.cad.Car+ ,表示继承该类的 所有⼦类包括本身

切点表达式由切点函数组成,execution是最常用的切点函数,语法为:

 修饰符和异常可以省略。

以上AOP部分的代码就已经完成,可以实现AOP的功能了,我们简单演示一下:

定义一个类来试一下它集中处理的实现:

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RequestMapping("/user")
@RestController
public class UserController {
    @RequestMapping("/login")
    public String login(){
        log.info("login..");
        return "login...";
    }
    @RequestMapping("set")
    public String setup(){
        log.info("setup...");
        return "setup....";
    }
    @RequestMapping("/logout")
    public String logout(){
        log.info("logout...");
        return "logout.....";
    }
}

在浏览器执行过后就会发现执行结果:(任意执行一个方法,这里执行第三个方法)

 可以看到五类通知的执行顺序如上,但是还有一个AfterThrowing没有看到打印,为什么呢?

这是因为AfterThrowing是在出现异常后才会进行打印的,在diamagnetic中插入一条异常代码,我们就会看到他的打印了:

以上代码能看出来了,AOP的确实一类事情的集中处理,且处理的时候不会破坏原有的代码,且允许用户自定义切面。

AOP概念 和 使用_第2张图片

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