【Sprig AOP】

目录

1 AOP 的思想

2 AOP 的组成

2.1 切面

3 AOP 的实现

3.1 添加 Spring AOP 依赖

3.2 定义切面

3.3 定义切点

3.4 实现通知

4 AOP 实现的一个例子


1 AOP 的思想

机场里有多家公司,但是安检是进候机室之前统一安排的,不需要不同航空公司各自安排一次安检。在计算机领域,也有类似的思想——AOP。

AOP(Aspect Oriented Programming):⾯向切⾯编程,它是⼀种思想,它是对某⼀类事情的集中处理。⽐如⽤户登录权限的效验,没学 AOP 之前,我们所有需要判断⽤户登录的⻚⾯(比如博客系统,所有需要用户登录的页面),都要各⾃实现或调⽤⽤户验证的⽅法,然⽽有了 AOP 之后,我们只需要在某⼀处配置⼀下,所有需要判断⽤户登录⻚⾯就全部可以实现⽤户登录验证了,不再需要每个页面都写相同的⽤户登录验证了。

AOP 是⼀种思想,⽽ Spring AOP 是⼀个框架,实现了 AOP 思想,两者之间的关系很像 MVC 与 Spring MVC 。

2 AOP 的组成

2.1 切面

切⾯(Aspect)由切点(Pointcut)和通知(Advice)组成。

切面:定义事件,也就是规定 AOP 要处理什么。比如用户登录效验

切点:定义具体规则,比如用户登录的拦截规则

通知:AOP 执行的具体方法,比如获取用户登录信息,如果已获取到说明已经登录了,否则就是未登录状态。

三者之间的关系类似于,公司的老板决定公司的业务是什么,而中层则来制定如何做事情的规则,最后由底层的劳动人民来实施具体的工作。

 

3 AOP 的实现

3.1 添加 Spring AOP 依赖

引入 Spring AOP 依赖:

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

3.2 定义切面

切面是一个类。需要两个注解。一个是 @Aspect ,表明该类是一个切面。

要让切面随着项目的启动而启动,因此要添加六大注解之一。这样才不会让那些在切面中定义的切点等方法,失去用处。

@Aspect //表明这个类是个 切面
@Component // 需要六大注解之一,以便在程序启动的时候便启动
public class UserAspect {
        ......
}

3.3 定义切点

切点表达式由切点函数组成,其中 execution() 是最常⽤的切点函数,⽤来匹配⽅法,语法为:

execution(<修饰符><返回类型><包名+类名+方法(参数)><异常>)

修饰符和异常通常可以省略。* 表示任意。 

拦截 包名+类名 的所有方法的返回值

    // 切点
    // 包名 + 类名
    @Pointcut("execution(* com.example.demo.controller.UserController.*(..))")
    public void pointcut(){
    }

3.4 实现通知

通知的方法:

前置通知使⽤@Before:通知⽅法会在⽬标⽅法调⽤之前执⾏。 后置通知使⽤

@After:通知⽅法会在⽬标⽅法返回或者抛出异常后调⽤。 返回之后通知使⽤@AfterReturning:通知⽅法会在⽬标⽅法返回后调⽤。 抛异常后通知使⽤@AfterThrowing:通知⽅法会在⽬标⽅法抛出异常后调⽤。 环绕通知使⽤

@Around:通知包裹了被通知的⽅法,在被通知的⽅法通知之前和调⽤之后执 ⾏⾃定义的⾏为。

4 AOP 实现的一个例子

package com.example.demo.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/getuser")
    public String getUser(){
        System.out.println("do getUser");
        return "get user";
    }
}
package com.example.demo.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/art")
public class ArticleController {
    @RequestMapping("/getart")
    public String getArticle(){
        System.out.println("do getArticle");
        return "getArticle";
    }
}

package com.example.demo.common;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;

@Aspect //表明这个类是个 切面
@Component // 需要六大注解之一,以便在程序启动的时候便启动
public class UserAspect {
    // 切点
    // 包名 + 类名 
    @Pointcut("execution(* com.example.demo.controller.UserController.*(..))")
    public void pointcut(){

    }

    // 前置通知
    // 需要指定切点的方法名,针对那个切点做出的具体方法实现。
    @Before("pointcut()")
    public void doBefore(){
        System.out.println("执行了前置通知");
    }

    // 后置通知
    @After("pointcut()")
    public void doAfter(){
        System.out.println("执行了后置通知");
    }

    // 环绕通知
    // 接受的参数类型一定是 ProceedingJoinPoint ,写死的
    @Around("pointcut()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("环绕通知执行之前");
        // 执行目标方法
        Object result = joinPoint.proceed();
        System.out.println("环绕通知执行之后");
        return result;
    }
}

【Sprig AOP】_第1张图片


【Sprig AOP】_第2张图片

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