SpringAOP面向切面编程

一、SpringAOP

1、基本概念

  • SpringAOP是面向切面编程,是一种技术,是spring的框架下的技术之一
  • 作用:在程序运行期间,不修改源码对已有方法进行增强(底层原理是动态代理技术)通用任务如安全、事务、日志等进行集中式管理,从而提供了更好的复用
  • 依赖:
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2、 在AOP 这种思想还没有出现的时候,我们解决 切面的问题思路无非有以下两种:

  • 方式一:通过静态方法实现(缺点:需要修改源码,后期不好维护)把需要添加的代码抽取到一个地方,然后在需要添加那些方法中引用;

  • 方式二:通过继承方案来解决(缺点:需要修改源码,继承关系复杂,后期不好维护),抽取共性代码到父类, 子类在需要的位置,调用父类方法。(抽取代码过程中就修改了源码)

    其实AOP 字面直译过来是面向切面编程,其实通俗一点它就是对我们的具体某个方法进行了增强而已。在之前我们对某个方法进行增强无非是两种手段 ,一种是装饰者模式 、 一种是代理模式 (静态代理 & 动态代理) 。 AOP 的底层使用的是动态代理方式

3.AOP主要术语

  1. JoinPoint: 连接点
    类里面哪些方法可以被增强,这些方法称为连接点. 在spring的AOP中,指的是所有现有的方法。
  2. Pointcut: 切入点
    在类里面可以有很多方法被增强,但是实际开发中,我们只对具体的某几个方法而已,那么这些实际增强的方法就称之为切入点
  3. Advice: 通知/增强
    增强的逻辑、称为增强,比如给某个切入点(方法) 扩展了校验权限的功能,那么这个校验权限即可称之为增强 或者是通知
    通知分为:
    前置通知: 在原来方法之前执行.
    后置通知: 在原来方法之后执行. 特点: 可以得到被增强方法的返回值
    环绕通知:在方法之前和方法之后执行. 特点:可以阻止目标方法执行
    异常通知: 目标方法出现异常执行. 如果方法没有异常,不会执行. 特点:可以获得异常的信息
    最终通知: 指的是无论是否有异常,总是被执行的
  4. Aspect: 切面
    切入点和通知的结合(在切面类编写通知的逻辑(前置还是后置),按照规则在切面类中编写哪些通知需要跟哪些切点联系)

二、代码的实现

切面类(编写切入规则和通知规则,有点像动态代理的处理器类)
客户端(客户端中有切点,就是实际需要被增强的方法)

  1. 切面类
@Aspect
@Component
public class MyAspect {
    /**
     * 定义需要拦截的东西,这里介绍两个常用的表达式:一个是使用 execution(),另一个是使用 annotation()。
     * 1.以 execution(* com.mutest.controller..*.*(..))) 表达式为例:
     * 第一个 * 号的位置:表示返回值类型,* 表示所有类型。
     * 包名:表示需要拦截的包名,后面的两个句点表示当前包和当前包的所有子包,在本例中指 com.mutest.controller包、子包下所有类的方法。
     * 第二个 * 号的位置:表示类名,* 表示所有类。
     * *(..):这个星号表示方法名,* 表示所有的方法,后面括弧里面表示方法的参数,两个句点表示任何参数。
     * 2.annotation() 方式是针对某个注解来定义切点,比如我们对具有 @PostMapping 注解的方法做切面,可以如下定义切面,也可以自定义注解
     * 
     */
     //AopController类下的save方法需要被增强
    @Before("execution(* com.itan.springAOP..AopController.save(..))")
    public void pointCut() {
        System.out.println("执行了execution的拦截方法");
    }

//切入点的方法:所有被PostMapping注解修饰的方法都会被advice通知
    @Before("@annotation(org.springframework.web.bind.annotation.PostMapping)")
    public void checkPrivilege() {
        System.out.println("get请求权限校验了");
    }
      //对标记有自定义注解PermissionAnnotation的方法进行增强
    @Before("@annotation(com.itan.springAOP.PermissionAnnotation)")
    public void checkPrivilege01() {
        System.out.println("PermissionAnnotation注解方法校验了");
    }
  1. 客户端类
@RestController
@RequestMapping("/aop")
public class AopController {

    @Autowired
    private AopService aopService;

    @GetMapping("/save")
    public String save() {
        String s = aopService.save();
        return s;
    }

    @PostMapping("/update")
    public String update() {
        return "更新成功";
    }
    @PostMapping("/permission")
    @PermissionAnnotation()
    public String permission() {

        return "自定义注解";

    }


}
  1. 自定义注解
/**
 * 自定义注解()
 * 1.元注解:@Target指明此注解用在哪个位置,如果不写默认可以用在任何位置上
 * TYPE:用在类,接口上
 * FIELD:用在成员变量上
 * METHOD:用在方法上
 * PARAMETER:用在参数上
 * CONSTRUCTOR:用在构造方法上
 * LOCAL_VARIABLE:用在局部变量上
 * 2.元注解:@Retention定义注解生命周期
 * SOURCE:注解只存在于Java源代码中,编译生成的字节码文件中就不存在了
 * CLASS:注解存在于Java源代码、编译以后的字节码文件中,运行的时候内存中没有,默认值
 * RUNTIME:注解存在于Java源代码中、编译以后的字节码文件中、运行时内存中,程序可以通过反射获取该注解
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PermissionAnnotation {

}
  1. 小结:
    可以看出,AOP比动态代理更加简洁,切面类+客户端就可以,到底需要有继承接口的委托者类还是没有继承接口的委托者类,这些不用管;直接在切面类中告诉spring,哪些类哪些方法那些注解标记的方法需要被增强就行
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值