Spring Aop 底层责任链思路实现

责任链模式实现方式以及在业务中的运用 我们在平常业务开发或者深入了解一些框架实现时,经常会看到责任链模式的运用。责任链模式,通俗来讲,是若干个处理器组成一条链,当收到请求时,依次经过每个处理器,每个处理器只负责单独的一块逻辑。实现责任链模式有很多种方式,我们由浅入深,共同来探讨如何来实现责任链模式。 考虑一个场景,当我们接受一个用户请求,需要先做登录验证、权限验证、业务验证等许多验证,然后再做业务处理。我们首先想到的是将登录、权限、业务这些验证抽象成一个个过滤器,类似于这样: public interface Filter { void 阅读详情

动手AOP责任链实现

简单了解 AOP

Spring 的两个重要特性之一 AOP 面向切面编程

image-20230204155405588

它的作用简单来说就是解耦 可以通过代理类的方式实现在不改变类本身的代码的情况下做到功能上的增强 , 了解它能做些什么我们就可以去思考怎么去实现它 , 这里涉及到责任链模式 (后续在细说) 。

想要去实现简单的aop 我们至少要做到 :

  • 拥有目标类
  • 动态代理目标类
  • 自定义通知方法

在实现aop 之前呢 我们需要简单复习一些前置知识 在复习之前 确认使用的依赖和版本 避免demo出现意外的bug

Java版本 : 1.8

Maven 版本 : 3.6.x

依赖

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.1.6.RELEASE</version>
    </dependency>

动态代理(代理目标类)

了解代理,我们需要复习一下代理的知识。

目前来看 代理分为两种 ,用文字就可以很简单的讲述静态代理和动态代理。

  • 静态代理可以实现代理 但是受限制于抽象类,无法去代理抽象类之外的对象
  • 动态代理依赖反射机制 可以实现对任何类的代理

创建目标类

我们就用Userservice 来作为我们的代理目标类

public class UserService {
    
    public Object insert  ()
    {
        System.out.println("==插入用户成功==");
        return "user insert ok";
    }
    
}

创建代理工厂

这里我们使用cglib 来作为动态代理的方式, 其实通过实现动态代理的支持类我们就可以实现简单的 aop 增强 ,

代码案例

public class ProxyFactory implements MethodInterceptor {
    private Object target;

    public UserService getProxy(Object target){
        //被代理对象
        this.target = target;
        //cglib 生成代理对象
        Enhancer enhancer = new Enhancer();
        //设置父类
        enhancer.setSuperclass(target.getClass());
        //设置回调
        enhancer.setCallback(this);
        //设置类加载器
        enhancer.setClassLoader(target.getClass().getClassLoader());
        //生成代理对象
        return (UserService)enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        //执行目标方法
        Object result = null;

        try {
            //前置通知
            System.out.println("前置通知");
             result = method.invoke(target, objects);

            //    返回通知
            System.out.println("返回通知");
        } catch (Throwable e) {
            //异常通知
            System.out.println("异常通知");
            throw new RuntimeException(e);
        } finally {
        //    后置通知
            System.out.println("后置通知");
        }

        return result;
    }
}

测试
public class Run {
    public static void main(String[] args) {
        UserService userService = new UserService();
        userService.insert();
        UserService userService1 = new ProxyFactory().getProxy(userService);
        userService1.insert();

    }
}

image-20230204163324899

只要我们在 标有注释的地方添加代码 是不是简单的切面增强就成了 ,这个时候就会有一个需要思考的问题, 想想我们在Spring 中使用的AOP,在标注切面和增强注解的情况下,Spring才帮我们去实现切面增强 。

所以到这里才是刚刚开始 ,我们使用AOP 的本意是什么 解耦 如果想上面案例这样写的话 岂不是掩耳盗铃, 本类解耦了 代理工厂耦合又高了起来 完全没有达到效果 所以接下来 我们要去解决这个问题

  • 提供灵活性
  • 解耦合
  • 是不是可以使用设计模式来解决问题呢

责任链模式

我们希望使用设计模式来增加我们自己demoAOP 的 灵活性,这里简单的介绍一下责任链模式

为了避免请求发送者与多个请求处理者耦合在一起,将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。

PS: 递归

image-20230204164417938

那我们实现责任链模式的结构是什么呢?

image-20230204164549365

这里我们实现前置增强来演示 责任链模式的上手思路

责任链

我们用递归的方式来做通知的不断调用

public class Chian {

    //记录index下标
    private int index=  -1;
    private List<BaseAdvice> adviceList;

    public Chian(List<BaseAdvice> adviceList) {
        this.adviceList = adviceList;
    }

    public Object proeccd() throws Throwable{
        if(index == adviceList.size()-1){
            System.out.println("==执行目标方法==");
            return null;
        }
        return  adviceList.get(++index).execute(this);
    }
}

增强通知基类

public abstract class BaseAdvice {

    public abstract Object execute(Chian chian) throws Throwable;

}

前置增强类

public class BeforeAdvice extends BaseAdvice{
    @Override
    public Object execute(Chian chian) throws Throwable {
        /*
        * 只做逻辑增强
        * 如果还有继续调用链的下一个通知
        * */
        System.out.println("前置通知");
        //调用链通知
        return   chian.proeccd();
    }
}

测试

public static void main(String[] args) throws Throwable {
     List<BaseAdvice> adviceList = new ArrayList<>();
    adviceList.add(new BeforeAdvice());
    Chian chian = new Chian(adviceList);
    chian.proeccd();
}

image-20230204170548913

可以看出来结果是与之前的代理方法结果是一致的,通过链式调用+递归来完成目标解耦并且增加灵活性

实现AOP

增强实现

四种增强 这里没有实现环绕增强,因为环绕相当于是其他增强的组合

基类

public abstract class BaseAdvice {

    public abstract Object execute(Chian chian) throws Throwable;

}

四种增强类

前置增强

public class BeforeAdvice extends BaseAdvice{
    @Override
    public Object execute(Chian chian) throws Throwable {
        /*
        * 只做逻辑增强
        * 如果还有继续调用链的下一个通知
        * */
        System.out.println("前置通知(责任链)");
        //调用链通知
        return   chian.proeccd();
    }
}

后置增强

public class AfterAdvice extends BaseAdvice{
    @Override
    public Object execute(Chian chian) throws Throwable {

        try {
            return chian.proeccd();
        } finally {
            System.out.println("后置增强");
        }
    }
}

异常处理增强

public  class ThrowAdvice extends  BaseAdvice{
    @Override
    public Object execute(Chian chian) throws Throwable {
        try {
            return chian.proeccd();
        } catch (Throwable e) {
            System.out.println("异常通知");
            throw new RuntimeException(e);
        }

    }
}

返回处理增强通知

public class ReturnAdvice extends BaseAdvice{
    @Override
    public Object execute(Chian chian) throws Throwable {
        //如果没有异常就走返回通知
        Object value = chian.proeccd();
        System.out.println("返回通知");
            return value;
    }
}

责任链实现

用链表+递归实现责任链,用链表数据结构的特点 来节点调节点执行增强

public class Chian {

    //记录index下标
    private int index=  -1;
    private List<BaseAdvice> adviceList;

    //目标方法
    private Method method;

    //方法参数
    private  Object[] args;
    //目标对象
    private  Object target;

    public Chian(List<BaseAdvice> adviceList) {
        this.adviceList = adviceList;
    }

    public Chian(List<BaseAdvice> adviceList, Method method, Object[] args, Object target) {
        this.adviceList = adviceList;
        this.method = method;
        this.args = args;
        this.target = target;
    }

    public Object proeccd() throws Throwable{
        if(index == adviceList.size()-1){
            return method.invoke(args,target);
        }
        return  adviceList.get(++index).execute(this);
    }
}

代理类实现

public class ProxyFactoryAddChian implements MethodInterceptor {
    private Object target;
    private List<BaseAdvice> adviceList;

    public ProxyFactoryAddChian() {
        adviceList = new ArrayList<>();
        adviceList.add(new BeforeAdvice());
        adviceList.add(new ReturnAdvice());
        adviceList.add(new AfterAdvice());
        adviceList.add(new ThrowAdvice());
    }

    public UserService getProxy(Object target){
        //被代理对象
        this.target = target;
        //cglib 生成代理对象
        Enhancer enhancer = new Enhancer();
        //设置父类
        enhancer.setSuperclass(target.getClass());
        //设置回调
        enhancer.setCallback(this);
        //设置类加载器
        enhancer.setClassLoader(target.getClass().getClassLoader());
        //生成代理对象
        return (UserService)enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        //在生产代理的时候就把链设置好
        Chian chian = new Chian(adviceList,method,objects,target);
        return chian.proeccd();
    }
}

测试

public class Run {
    public static void main(String[] args) throws Throwable {
        UserService userService = new UserService();
        //userService.insert();
        UserService userService1 = new ProxyFactoryAddChian().getProxy(userService);
        userService1.insert("编程导航小冷Demo");
    }
}

image-20230204195338199

总结

实现增强功能其实我们就是将输出语句的位置都换成想要实现的代码就可以了,可能看起来有些疑问 ,这和spring的AOP并不是完全像,那是因为 AOP 有部分是有ioc的参与的 但是很巧,我们之前实现过ioc

如果这个系列更新的还好的话 之后可以尝试做个小型的Spring。 和小冷一起读spring源码在去根据自己想想怎么用自己的思路去实现。

那么这次的责任链动手实践 我们都学到了什么呢 ?

  • 责任链模式的应用
  • 递归的运用
  • 学习到类优秀框架源码的思路
  • 获得一个半成品的aopdemo

希望大伙可以继续观看小冷的技术文章 一起进步 你们的观看可以给予小冷莫大的鼓励

谢谢观看 请期待下一篇

Spring事务与AOP原理深度解析:从注解到动态代理的实现机制 在Java企业级开发中,面向切面编程(AOP)是一种重要的设计范式,其核心思想是将横切关注点(如事务管理、日志记录)从核心业务逻辑中分离,实现代码的解耦与复用。AOP通过动态代理技术,在不修改源代码的情况下,为方法调用添加额外行为,这一机制正是Spring框架实现声明式事务管理的基石。Spring事务的本质是利用AOP拦截目标方法,在方法执行前后自动处理事务的开启、提交与回滚,从而将开发者从繁琐的模板代码中解放出来。这种设计不仅提升了代码的整洁度,还确保了事务的一致性与可靠性。在实际应用中,Spring事务 阅读详情

相关推荐

Spring AOP环绕通知:原理、核心应用与深度避坑指南

面向切面编程(AOP)是Spring框架中用于处理横切关注点的核心技术,它通过将通用逻辑(如日志、事务)与业务逻辑分离,提升了代码的模块化和可维护性。其核心原理是基于动态代理或字节码增强,在运行时将通知织入到目标方法的连接点。这项技术的核心价值在于实现了关注点分离,让开发者能够集中处理系统级的通用功能。在实际工程中,AOP被广泛应用于性能监控、声明式事务管理、安全控制和缓存等场景。环绕通知(@Around)作为Spring AOP中最强大的通知类型,它本质上是一个可编程的方法拦截器,能够完全控制目标方法的执

weixin_30954265的博客 317

spring aop学习9:Aop的链式调用(责任链模式)

一.责任链模式 1.基本的责任链模式 ◆主体父类:abstract class Subject.javapackage com.tiglle.responsibility.chain.model; //主体 public abstract class Subject { private Subject successor; protected abstract void handle

Tiglle的博客 4873

SpringAOP之探秘(动态代理、责任链模式、注解使用)

SpringAOP之探秘(动态代理、责任链模式、注解使用)- 详情:https://blog.youkuaiyun.com/Dream_Weave/article/details/85008674

Spring AOP中的责任链设计模式

前面简单的写了下Spring AOP中是怎么实现动态代理的,简单的来说是通过bean对象的后置管理器对实例化的bean对象做判断后使用不同的动态代理方式,下面来看一下生成的动态代理是怎么执行的。

李永志的博客 1620

set_data_check专题[使用,report_timing,setup/hold检查]

set_data_check用于约束『数据-对-数据』的『建立保持』时间检查,通常被称为非时序约束 ( non-sequential constraints ), 理论上set_data_check 可以设在任意的两个data pin 上,其中一个pin 称为 constrained pin 类似于寄存器的data pin, 另一个pin 称为related pin 类似于寄存器的clock pin.

cy413026的博客 1万+

车载监控系统升级指南:如何用XS9950A替换TP9950实现高清视频解码(附配置代码)

本文提供了从TP9950升级至XS9950A车载视频解码芯片的完整实战指南。详细解析了硬件设计调整、PCB布局要点,并重点分享了通过I2C配置寄存器实现高清HDCCTV视频解码与同轴音频集成的软件驱动代码与调试技巧,助力工程师平滑完成系统升级。

weixin_29268637的博客 375

SpringAOP中责任链模式的原理浅析(自己动手实现一个简易的责任链与SpringAOP源码学习)

2021.4.18 本文参考博客: 点击查看原文 根据其原文用代码实现,并作图理解。 目录责任链模式自己简单实现一个责任链模式分析代码 责任链模式 一个对象被多个拦截器拦截处理时,我们称这样的设计模式为责任链模式。 重点是其中在多个拦截器中,对象都是同一个,这样做能让处理始终围绕一开始的对象。 责任链模式在Filter过滤器和Spring的Interceptor里面都常常用到。 自己简单实现一个责任链模式 先画出UML的类图,大致的关系如下: 可以看出上面有三个接口,三个实现类。 接口代码分别是: 连接点

安洁莉娅丶的博客 1053

Spring AOP相关知识详解

AOP知识大全(不全)

乾坤未定,你我皆是黑马 1228

全志 mipi屏幕和触摸驱动调试记录

mipi屏幕与触摸调试记录

u011996684的博客 3220

手把手教你用海康威视相机+DLP4500搭建双目结构光系统(附避坑指南)

本文详细介绍了如何使用海康威视相机和DLP4500搭建双目结构光三维测量系统,涵盖硬件选型、系统搭建、双目标定及三维重建等关键步骤。特别针对预算有限的开发者和实验室团队,提供实用的避坑指南和优化技巧,帮助实现0.02mm的高精度测量。

weixin_42526087的博客 462

互联网架构-Spring5.0源码深度解析-024:SpringBean的Aop通知调用链源码分析

024:SpringBean的Aop通知调用链源码分析1 SpringAop底层调用链源码分析演示2 SpringAop底层源码流程回顾3 循环遍历与递归算法实现的区别4 纯手写SpringAop调用链思路分析5 纯手写SpringAop调用链代码016 纯手写SpringAop调用链代码027 纯手写SpringAop调用链代码03 1 SpringAop底层调用链源码分析演示 课程内容: 1.SpringAop源码分析之通知调用链关系 2.递归算法与循环算法区别 3.基于递归算法+责任链模式实现Spri

枫火的博客 322

OpenTCS打造移动机器人交通管制系统(四)

先分析下OpenTCS的一些策略方面的东西,这是OpenTCS的基础。 首先需要先明确下OpenTCS内核中的三个概念: 路由(Route) : 决定了车辆通过什么样的方式和算法来获得一段路径,未来车辆将沿着此路径运行。 派遣(Dispacher): 决定了一个订单应该关联哪一辆小车,即为订单分配车辆和为车辆分配订单。 调度(schedule):狭义上的调度,交通管制的核心,决定了何时分配...

白色冰激凌的技术专栏 5272

spring-aop

aop概念 AOP技术利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为“Aspect”,即切面。所谓“切面”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。AOP代表的是一个横向的关系,如果说“对象”是一个空心的圆柱体,其中封装...

sinat_34814635的博客 570

RK3566/RK3588 NPU性能实测:用mobilenet模型快速验证你的开发板NPU是否正常工作

本文提供了RK3566/RK3588开发板NPU性能实测指南,通过MobileNet模型快速验证NPU是否正常工作。详细介绍了环境搭建、测试资源获取、编译运行及结果分析的全流程,帮助开发者高效验证神经网络加速器功能,为后续AI应用部署奠定基础。

weixin_28826521的博客 449

超详细版risc-v五级流水线cpu硬件设计实现解析

深入剖析risc-v五级流水线cpu的硬件架构与设计细节,涵盖指令流程、模块划分与关键时序控制,帮助理解risc-v五级流水线cpu的工作机制与优化策略。

weixin_42437253的博客 1633

深入解析Spring AOP底层原理:从代理模式到性能调优实战

面向切面编程(AOP)是一种通过预编译或运行时动态代理,在不修改源代码的情况下为程序统一添加功能的编程范式。其核心原理基于代理模式,通过在方法调用前后插入增强逻辑,实现对横切关注点的模块化管理。这项技术的核心价值在于解耦业务逻辑与通用功能(如日志、事务、权限),提升代码的可维护性和复用性。在Java企业级开发中,Spring AOP作为其主流实现,广泛应用于事务管理、安全控制、性能监控和日志记录等场景。本文将聚焦Spring AOP的底层机制,特别是其默认使用的**JDK动态代理**与可选的**CGLIB代

450

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

Spring干货---AOP

springAOP

zhzhxian的博客 204

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

spring aop应用场景_02.面试指南Spring(上)

SpringFramework文章导读IOC/Bean的生命周期AOP事务面试套路对于面试官问的各个问题,我们首先要知道面试官问我们这个问题的目的是什么,他想从我这里得到什么答案,比如很多面试官喜欢问spring源码,其实并不是想要我们去背源码,是想我们遇到spring相关的问题时候可以快速的解决。套路分下面三点:我学习源码的过程是什么样的?通过学习源码,我解决过项目中的哪些问题源码的代...

weixin_39926749的博客 168

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Spring之AOP(切面思想)

Spring之AOP(切面思想)

小汤圆 157

Java 23 种设计模式:从踩坑到精通 | 代理模式 —— 你的 AOP 就是用代理实现的

摘要:本文深入剖析了 Java 代理模式(Proxy Pattern)的三种实现形态(静态代理、JDK 动态代理、CGLIB 动态代理),并结合 Spring AOP 源码详细解读了代理机制的选择逻辑与自调用失效陷阱。文章从报表查询的性能优化场景切入,不仅涵盖了 MyBatis Mapper、RPC 框架等经典应用,还对比了装饰器模式,梳理了高频面试题,是 Java 开发者掌握“面向切面编程”基石的实战指南。

折哥|智能物流与Java实战,副高数据库工程师。深耕出版社物流WMS/OMS(线体/立库/VGA),也分享Java进阶与OMS电商对接。Oracle→PG实战派。相信沉淀可迁移能力,分享通用技术,不藏不虚。 1071

【AOP】AOP-面向切面编程 (系统性知识体系全解)

本文从基础认知、核心概念、底层原理、主流实现、工程应用、进阶特性、避坑实践、范式对比8大维度,构建AOP完整的知识体系,覆盖从入门到精通的全链路内容。

小江的记录本 618

spring

在应用开发中用的非常多, @Component注解是一个通用注解,可以用在于任何类上。包括普通java类,业务逻辑组件,持久化对象等等。通过@Component注解spring自动创建该类的实例注入SpringIOC容器中。@Bean是用于配置类中声明一个Bean的,它通常是用于配置类的方法上面,表示把这个方法的返回对象注册到Spring IOC容器中。通过@Bean自定义Bean的创建和初始化过程,包括指定Bean的名称、作用域、依赖关系等。1.用途不同@Component用于标识普通的类。

黑冰[̲̅V̲̅I̲̅P̅] 818

子类重写方法aop切不到_Spring5.0源码深度解析:SpringBean的Aop通知调用链源码分析,小白都能看懂...

点击上方“Java分享吧”,选择“设为星标”优选有价值的技术文献,从我做起源码分析篇章SpringAOP原理探究思考:springAOP底层运用了什么设计模式?生成代理类:代理设计模式、底层五个通知形成调用链采用:责任链设计模式下面我们回顾下SpringAop实现流程:1、配置@EnableAspectJAutoProxy:开启AOP权限2、@Import(AspectJAutoProx...

weixin_39619478的博客 176

Spring深度学习:动态代理源码解析

本文小豪将带大家深度学习Spring动态代理相关知识,包括JDK和Cglib两种动态代理的底层实现原理,以及代理对象回调时拦截链执行过程的源码分析,深入研究动态代理的内部机制,进一步理解面向切面编程的思想,提升我们的架构能力

Code豪客 1252

对线面试官day2-Spring基础,东软医疗java面试题目

2021年的金三银四一眨眼就到了,对于很多人来说是跳槽的好机会,大厂面试远没有我们想的那么困难,摆好心态,做好准备,你也可以的。另外,面试中遇到不会的问题不妨尝试讲讲自己的思路,因为有些问题不是考察我们的编程能力,而是逻辑思维表达能力;最后平时要进行自我分析与评价,做好职业规划,不断摸索,提高自己的编程能力和抽象思维能力。

2401_83977689的博客 756
上一篇: 图解设计模式: 有趣的工厂模式
下一篇: 重走前端路JS进阶篇:This 指向与箭头函数
冷环渊
博客等级 码龄7年 1130粉丝 176原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冷环渊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值