AOP(面向切面编程)

这篇具有很好参考价值的文章主要介绍了AOP(面向切面编程)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一.什么是AOP

AOP 为 Aspect Oriented Programming 的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP 是 OOP(面向对象编程)的延续,是软件开发中的一个热点,也是 Spring 框架中的一个重要内容,是函数式编程的一种衍生范型。利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,使用AOP进行编程,可以降低代码的侵入性,提高程序的可重用性,同时提高了开发的效率。

简单来说,aop是一种是一种思想和和规范,通过选择不同方法(可以在不同类)在不同时机(方法执行前、执行后、返回前后、抛出异常后...),对选择的方法统一添加处理逻辑。

springAOP是对AOP思想的一种具体实现,但是它只实现了对方法的增强,没有实现对属性的增强

二.AOP的典型应用场景

  • 统一的日志记录 
  • 统一的方法执行时间统计
  • 统一的返回格式设置
  • 统一的异常处理
  • 事务的开启和提交

三.关于AOP的核心知识点

切面类:定义一个类来组织方法增强的逻辑(内部由切点和通知组成)

切点(PointCut):定义要增强的方法(确定增强的范围)

Pointcut 的作用就是提供一组规则(使用 AspectJ pointcut expression language 来描述)来匹配 Join Point,给满足规则的 Join Point 添加 Advice

通知:定义方法增强的实现逻辑(定义何时增强以及如何增强)

定义了切面是什么,何时使用,其描述了切面要完成的工作,还解决何时执行这个工作的问题。

切点表达式说明

AspectJ 支持三种通配符:
* :匹配任意字符,只匹配一个元素(包,类,或方法,方法参数)。
* .. :匹配任意字符,可以匹配多个元素 ,在表示类时,必须和 * 联合使用。
+ :表示按照类型匹配指定类的所有类,必须跟在类名后面,如 com.cad.Car+ , 表示继承该类的所有子
类包括本身。
切点表达式由切点函数组成,其中 execution() 是最常用的切点函数,用来匹配方法,语法为:
execution(< 修饰符 >< 返回类型 >< . . 方法 ( 参数 )>< 异常 >)
修饰符 异常 可以省略。
表达式示例
AOP(面向切面编程)

定义相关通知

通知定义的是被拦截的方法具体要执行的业务,比如用户登录权限验证方法就是具体要执行的业务。Spring AOP 中,可以在方法上使用以下注解,会设置方法为通知方法,在满足条件后会通知本方法进行调用:
前置通知使用@Before:通知方法会在目标方法调用之前执行。
后置通知使用@After:通知方法会在目标方法返回或者抛出异常后调用。
返回之后通知使用@AfterReturning:通知方法会在目标方法返回后调用。
抛异常后通知使用@AfterThrowing:通知方法会在目标方法抛出异常后调用。
环绕通知使用@Around:通知包裹了被通知的方法,在被通知的方法通知之前和调用之后执行自定义 的行为。

四.AOP的实现原理

Spring AOP 是构建在 动态代理 基础上,因此 Spring AOP 的支持局限于方法级别的拦截
Spring AOP 支持 JDK Proxy CGLIB 方式实现动态代理。默认情况下,实现了接口的类(被代理类),使用 AOP 会基于 JDK 生成代理类,没有实现接口的类,会基于 CGLIB 生成代理类。
AOP(面向切面编程)
对于使用JDK实现的动态代理:代理类和被代理类要实现同一个接口,在实现的过程中会使用到的
 api如下:Invocationhandler,proxy.newProxyInstance
对于基于GCLIB实现的动态代理:继承原始类(原始类不能被final修饰),是专门生成代理类的第三方框架,是基于asm字节码框架生成的
JDK CGLIB 的区别
1. JDK 实现,要求被代理类必须实现接口,之后是通过 InvocationHandler Proxy,在运行时动态的在 内存中生成了代理类对象,该代理对象是通过实现同样的接口实现(类似静态代理接口实现的方式), 只是该代理类是在运行期时,动态的织入统一的业务逻辑字节码来完成。
2. CGLIB 实现,被代理类可以不实现接口,是通过继承被代理类,在运行时动态的生成代理类对象。
织入( Weaving ):代理的生成时机
织入是把切面应用到目标对象并创建新的代理对象的过程,切面在指定的连接点被织入到目标对象中。
在目标对象的生命周期里有多个点可以进行织入:
编译期: 切面在目标类编译时被织入。这种方式需要特殊的编译器。 AspectJ 的织入编译器就是以这种
方式织入切面的。
类加载器: 切面在目标类加载到 JVM 时被织入。这种方式需要特殊的类加载器( ClassLoader , 它可以 在目标类被引入应用之前增强该目标类的字节码。AspectJ5 的加载时织入( load-timeweaving. LTW
就支持以这种方式织入切面。
运行期: 切面在应用运行的某一时刻被织入。一般情况下,在织入切面时, AOP 容器会为目标对象动态创建一个代理对象。SpringAOP 就是以这种方式织入切面的。

五.AOP的实现方式

JDK和GCLIB实现的代理类如下:

JDK

import org.example.demo.service.AliPayService;
import org.example.demo.service.PayService;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

//动态代理:使用JDK提供的api(InvocationHandler、Proxy实现),此种方式实现,要求被代理类必须实现接口
public class PayServiceJDKInvocationHandler implements InvocationHandler {
    //目标对象即就是被代理对象
    private Object target;

    public PayServiceJDKInvocationHandler(Object target) {
        this.target = target;
    }

    //proxy代理对象
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws
            Throwable {
//1.安全检查
        System.out.println("安全检查");
//2.记录日志
        System.out.println("记录日志");
//3.时间统计开始
        System.out.println("记录开始时间");
//通过反射调用被代理类的方法
        Object retVal = method.invoke(target, args);
//4.时间统计结束
        System.out.println("记录结束时间");
        return retVal;
    }

    public static void main(String[] args) {
        PayService target = new AliPayService();
//方法调用处理器
        InvocationHandler handler =
                new PayServiceJDKInvocationHandler(target);
//创建一个代理类:通过被代理类、被代理实现的接口、方法调用处理器来创建
        PayService proxy = (PayService) Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                new Class[]{PayService.class},
                handler
        );
        proxy.pay();
    }
}

GCLIB

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import org.example.demo.service.AliPayService;
import org.example.demo.service.PayService;

import java.lang.reflect.Method;

public class PayServiceCGLIBInterceptor implements MethodInterceptor {
    //被代理对象
    private Object target;

    public PayServiceCGLIBInterceptor(Object target) {
        this.target = target;
    }

    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy
            methodProxy) throws Throwable {
//1.安全检查
        System.out.println("安全检查");
//2.记录日志
        System.out.println("记录日志");
//3.时间统计开始
        System.out.println("记录开始时间");
//通过cglib的代理方法调用
        Object retVal = methodProxy.invoke(target, args);
//4.时间统计结束
        System.out.println("记录结束时间");
        return retVal;
    }

    public static void main(String[] args) {
        PayService target = new AliPayService();
        PayService proxy = (PayService) Enhancer.create(target.getClass(), new
                PayServiceCGLIBInterceptor(target));
        proxy.pay();
    }
}


 

六.AOP的使用

SpringAOP在使用时主要有以下两种使用方式:
①使用aspectj风格的注解进行开发:

添加依赖

 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

定义通知时机和通知逻辑

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

/**
 * @author tongchen
 * @create 2023-05-08 11:14
 */
@Aspect
//将配置加载到容器中
@Component
public class AopConfig {
    //定义切点
    //包后面一定要有一个空格
    @Pointcut("execution(* com.ljl..service.*Service.*(..))")
    public void pointCut(){

    }
    @Around("pointCut()")
    public Object around(ProceedingJoinPoint joinPoint){

        //pointcut匹配的方法
        try {
            Long start=System.currentTimeMillis();
            Object proceed = joinPoint.proceed();
            Long end=System.currentTimeMillis();
            System.out.println("方法运行的时间:"+(end-start));
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
        return null;
    }

}

定义切点方法

import org.springframework.stereotype.Service;

import java.util.ArrayList;

/**
 * @author tongchen
 * @create 2023-05-08 11:13
 */
@Service
public class AspectService {
    public Object timeTest(){
        //模拟获取数据库中的数据
        return new ArrayList<Integer>();
    }
}

②定义一个类,实现MethodInteceptor文章来源地址https://www.toymoban.com/news/detail-450352.html

到了这里,关于AOP(面向切面编程)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • AOP 面向切面编程 入门练习

    添加依赖 Spring配置文件 接口类和实现类 切面类 测试类

    2024年04月11日
    浏览(42)
  • JAVA:面向切面编程AOP

            把某一些功能提取出来与某一对象进行隔离,提取之后可以对某哥单方面的功能进行修改和扩展         也就是把众多方法中的的所有公共代码抽取出来,放到某个地方集中管理         对业务逻辑的各个部分进行了隔离,从而降低业务逻辑各部分之间的耦合,

    2024年02月07日
    浏览(50)
  • [SSM]Spring面向切面编程AOP

    目录 十五、面向切面编程AOP 15.1AOP介绍 15.2AOP的七大术语 15.3切点表达式 15.4使用Spring的AOP 15.4.1准备工作 15.4.2基于AspectJ的AOP注解式开发 15.4.3基于XML配置方式的AOP(了解) 15.5AOP的实际案例:事务处理 15.6AOP的实际案例:安全日志 IoC使软件组件松耦合。AOP让你能够捕捉系统中经

    2024年02月15日
    浏览(46)
  • 认识 spring AOP (面向切面编程) - springboot

    本篇介绍什么是spring AOP, AOP的优点,使用场景,spring AOP的组成,简单实现AOP 并 了解它的通知;如有错误,请在评论区指正,让我们一起交流,共同进步! 本文开始 AOP: 面向切面编程,也就是面向某一类编程,对某一类事情进行统一处理; spring AOP: 是实现了AOP这种思想的一

    2024年02月14日
    浏览(49)
  • Spring AOP(面向切面编程)和方法拦截

    Spring AOP(面向切面编程)和方法拦截 Spring是一款广泛使用的Java开发框架,提供了丰富的功能和工具,用于简化企业级应用程序的开发。其中一个重要的特性是面向切面编程(AOP)和方法拦截。本文将介绍Spring AOP和方法拦截的概念、工作原理以及在实际开发中的应用。 在软

    2024年02月05日
    浏览(44)
  • 切面的魔力:解密Spring AOP 面向切面编程

    目录 一、AOP简介 1.1 什么是AOP ? 1.2 什么是面向切面编程 ? 1.3 AOP 的特点 二、 AOP的基本概念解读 2.1 AOP的基本概念 2.2 AOP 概念趣事解读 三、代码情景演示 3.1 编写目标对象(超级英雄们正常的行动) 3.2 编写通知类 3.2.1 前置通知 3.2.2 后置通知 3.2.3 异常通知 3.2.4 环绕通知

    2024年02月11日
    浏览(54)
  • 12AOP面向切面编程/GoF之代理模式

    先看一个例子: 声明一个接口: 实现该接口: 存在的问题: 核心功能与边缘功能掺杂(即计算的过程和sout掺杂) 边缘功能尽管重复,但却大量分散,不利于管理 目标: 将重复的代码统一提取,并且[[动态插入]]到每个业务方法! 用代理模式解决: 相关术语: 代理:将非

    2024年01月19日
    浏览(45)
  • 12.控制反转IOC与面向切面编程AOP

    目录 一、IOC-控制反转。 二、AOP-面向切面编程。 IOC(Inversion of Control)是控制反转的缩写,指的是将对象的创建过程和依赖关系的处理交给外部容器来实现,从而实现对象之间的解耦。因此,IOC不是容器,是一种编程思想,将对象之间的依赖关系的处理从程序中转移到容器(

    2023年04月09日
    浏览(62)
  • JAVA:使用 Spring AOP 实现面向切面编程

    1、简述 在现代的软件开发中,面向切面编程(AOP)是一种重要的编程范式,它允许我们将横切关注点(如日志记录、性能监控、事务管理等)从应用程序的核心业务逻辑中分离出来,以提高代码的模块化和可维护性。Spring 框架提供了强大的 AOP 支持,使得我们可以轻松地实

    2024年04月13日
    浏览(45)
  • 【Java 初级】Spring核心之面向切面编程(AOP)

    tip:作为程序员一定学习编程之道,一定要对代码的编写有追求,不能实现就完事了。我们应该让自己写的代码更加优雅,即使这会费时费力。 💕💕 推荐: 体系化学习Java(Java面试专题) AOP(面向切面编程)是一种编程范式,用于将横切关注点(如日志记录、性能统计等

    2024年02月04日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包