AOP-AspectJ 切面技术及使用MethodInterceptor实现切面

目录

一、简介

二、什么是AspectJ

AOP 思想概述

AOP 实现方式

AOP 特性概念

切点指示器 

 通知类型

三、实现AOP的方式

四、配置说明

自定义注解作为切点

 NeedCut 

 MyAop 

 GirlController 

继承MethodInterceptor实现切面

 MyMethodInterceptor

 AopConfig 

 NeedCut 注解

 GirlController 

 配置文件


一、简介

  1. 它不属于spring;

  2. AspectJ是一个AOP的框架;

  3. 定义了AOP语法;

  4. 有一个专门的编译器用来生成遵守Java字节编码规范的Class文件

二、什么是AspectJ

AspectJ是使用面向切面的一个框架

它扩展了Java语言(它本身也是一种语言)

支持原生Java代码 有自己的编译器

将代码翻译成Java字节码文件

是为了方便编写AOP代码而出现的

使用AOP编程的三个重点 通知 切点 织入

AOP 思想概述

AOP(Aspect Oriented Programming)是一种面向切面的编程思想。面向切面编程是将程序抽象成各个切面,即解剖对象的内部,将那些影响了多个类的公共行为抽取到一个可重用模块里,减少系统的重复代码,降低模块间的耦合度,增强代码的可操作性和可维护性。

AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处都基本相似。比如权限认证、日志、事务处理、增强处理。

AOP 实现方式

AOP 的初衷是,保证开发者不修改源代码的前提下,为系统中的业务组件添加某种通用功能。AOP 的本质是由 AOP 框架修改业务组件的源代码,达到增强功能的目的。按照 AOP 框架修改源代码的时机,可以将其分为两类:

  • 静态 AOP 实现:AOP 框架在编译阶段对程序源代码进行修改,生成了静态的 AOP 代理类(生成的 *.class 文件已经被改掉了,需要使用特定的编译器),比如 AspectJ。

  • 动态 AOP 实现:AOP 框架在运行阶段动态生成代理对象(在内存中以 JDK 动态代理,或 CGlib 动态地生成 AOP 代理类),如 SpringAOP。

AOP 特性概念

  • 通知(Advice): AOP 框架中的增强处理。通知描述了切面何时执行以及如何执行增强处理。

  • 连接点(Join point): 连接点表示应用执行过程中能够插入切面的一个点,这个点可以是方法的调用、异常的抛出。在 Spring AOP 中,连接点总是方法的调用。

  • 切点(PointCut): 可以插入增强处理的连接点。

  • 切面(Aspect): 切面是通知和切点的结合。

  • 引入(Introduction):允许我们向现有的类添加新的方法或者属性。

  • 织入(Weaving): 将增强处理添加到目标对象中,并创建一个被增强的代理对象。

切点指示器 

 通知类型

三、实现AOP的方式

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
 </dependency>
@Aspect
@Component
public class MyAOP {
    // 定义切入点
    @Pointcut("execution(* com.chensir.controller.*.*(..))")
    public void point() {}

    // 前置通知
    @Before("point()")
    public void before() {
        System.out.println("前置通知");
    }
    // 后置通知 始终会执行
    @After("point()")
    public void after() {
        System.out.println("后置通知");
    }
    // 环绕通知
    @Around("point()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("环绕前");
        Object result = pjp.proceed();
        System.out.println("环绕后");
        return result;
    }
    // 后置 发生异常时不会执行
    @AfterReturning("point()")
    public void returning() {
        System.out.println("After returning 后置");
    }
    // 发生异常
    @AfterThrowing("point()")
    public void throwing() {
        System.out.println("发生异常了");
    }

}

四、配置说明

//定义切入点
//两种占位符
//* 代表的是一个单词,b* 代表的是以b开头的单词。 例如 bds
//.. 通配符 ,代表的是0个或者多个匹配项
//@Pointcut("execution(* com.chensir.service..*.*(..))")  //com.chensir.service 下面以及子包所有类的所有方法
//@Pointcut("execution(* com.chensir.service..*.*(java.lang.String,..))")  //com.chensir.service 下面以及子包所有类的,第一个参数是String类型的方法
//@Pointcut("execution(* com.chensir.service.*.*(..))")  //com.chensir.service 下面所有类的所有方法
//execution(* com.bao.User.add(..))  com.bao.user类下面的add方法
//excution(* com.bao.user.*(..))   com.bao.user下的所用方法

//配置com.bao.User下的add()

execution(* com.bao.User.add(..))

//配置com.bao.User下的所有方法

execution(* com.bao.User.*(..))

//配置所有包下的所有方法

execution(**.*(..))

//配置所有包下的a开头方法

execution(* a*(..))

//配置com.service包下的所有类的所有方法

execution(* com.service.*.*(..)))

自定义注解作为切点

 NeedCut 

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Deprecated
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface NeedCut {
}

 MyAop 

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

@Aspect
@Component
public class MyAop {
    // 定义切入点
//    @Pointcut("execution(* com.chensir.controller.*.*(..))")
    @Pointcut("@annotation(com.chensir.annotation.NeedCut)")
    public void point() {}

    // 前置通知
    @Before("point()")
    public void before() {
        System.out.println("---------前置通知--------");
    }
    // 后置通知 始终会执行
    @After("point()")
    public void after() {
        System.out.println("----------后置通知-------");
    }
    // 环绕通知
    @Around("point()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("-------环绕前----------");
        Object result = pjp.proceed();
        System.out.println("---------环绕后-----------");
        return result;
    }

    // 后置 发生异常时不会执行
    @AfterReturning("point()")
    public void returning() {
        System.out.println("------After returning 后置------------");
    }

    // 发生异常
    @AfterThrowing("point()")
    public void throwing() {
        System.out.println("-------发生异常了----------");
    }

}

 GirlController 

@RestController
@RequestMapping("/api")
public class GirlController {

    @GetMapping("/kiss")
    @NeedCut
    public String kiss(){
        return "么么哒";
    }

    @GetMapping("/kiss2")
    public String kiss2(){
        return "么么哒";
    }
}

kiss使用了@NeedCut注解,调用时能够走aop拦截;而kiss2没有加@NeedCut注解,调用时不会走aop拦截

继承MethodInterceptor实现切面

 MyMethodInterceptor

import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

import java.lang.reflect.Method;



@Slf4j
public class MyMethodInterceptor implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        // 获取方法
        Method method = invocation.getMethod();
        //获取参数
        Object[] arguments = invocation.getArguments();
        //获取返回值
        Object proceed = invocation.proceed();
        log.info("方法:{},参数:{},返回值:{}", method.getName(), JSONUtil.toJsonStr(arguments), proceed);
        return proceed;
    }
}

 AopConfig 

import com.chensir.interceptor.MyMethodInterceptor;
import org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

@Configuration
public class AopConfig {

    @Value("${aop.MethodInterceptor.point}")
    private String point;

    @Bean
    public AspectJExpressionPointcutAdvisor aspectJExpressionPointcutAdvisor(){
        AspectJExpressionPointcutAdvisor advisor = new AspectJExpressionPointcutAdvisor();
        advisor.setAdvice(new MyMethodInterceptor());
        advisor.setExpression(point);
        return advisor;
    }
}

 NeedCut 注解

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Deprecated
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface NeedCut {
}

 GirlController 


@RestController
@RequestMapping("/api")
public class GirlController {

    @GetMapping("/kiss")
    @NeedCut
    public String kiss(Integer id){
        return "么么哒";
    }

    @GetMapping("/kiss2")
    public String kiss2(){
        return "么么哒";
    }
}

 配置文件


#aop.MethodInterceptor.point = execution(* com.chensir.controller.*.*(..))

# 使用注解方式
aop.MethodInterceptor.point = @annotation(com.chensir.annotation.NeedCut)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值