【模式】AOP{更新中}

Ubuntu升级遇到grub-efi-amd64-signed安装失败?3步搞定这个烦人错误 本文深度解析Ubuntu系统升级时grub-efi-amd64-signed安装失败并提示“cannot find EFI directory”错误的根本原因。该错误通常由EFI系统分区挂载异常、BIOS/UEFI引导模式不匹配或dpkg包状态死锁导致。文章提供了三步精准修复流程:首先检查并修复ESP分区挂载,其次处理dpkg依赖问题,最后针对传统BIOS系统提供适配方案,帮助用户安全彻底地解决这一常见升级难题。 阅读详情

 

代理模式

代理模式的产生:明星A会唱歌,很多人都想找A商演,A自己不会。经纪人B,作为明星A的代理,负责接收邀请,筛选邀请,安排演唱前后接送,粉丝公关等事宜。明星A只负责唱歌就可以了。

代理模式:抽象一下,经纪人B 这群人就是ProxyClass-代理类,而明星A 这群人就是Class。ProxyClass类向外提供 Class 所有的方法(功能)。外部只需调用ProxyClass的方法,就可以让Class完成对应功能。ProxyClass 可以对调用前后进行控制。比如当有人调用ProxyClass的m1让明星A唱歌的时候,其对参数进行筛选,再调用 Class 的 m1 让明星A去赴演。

代理模式的设计类图:可以看到ProxyClass拥有Class的所有方法,并调用Class的方法。我想肯定有人会问,为什么还需要画蛇添足让两个类实现同一个接口。一是一种对外申明,Class有的接口ProxyClass全能代理。二是Class可以有很多个代理类,代理类都具有共同的代理接口,其次不需要修改现有依赖Class/ProxyClass的代码。

 

代理模式
代理模式设计类图

 

 

JDK动态代理

JDK动态代理的产生:

  • 被代理类方法特别多,代理类要做的事情雷同:假设 明星A 十项全能,有很多才艺。经纪人B 在接收邀请后做的事情却都是筛选。那么需要完全手写一个新的类,然后定义所有明星A拥有的方法。
  • 被代理类内容更改:再者随着时间的推移,A的技能在不断变化,B也又要随之修改,非常繁杂。
  • 代理类更换被代理类:假设 经纪人B 不想再给 明星A 代理了,换了另一个 运动明星C,则又得根据 明星C 修改 经纪人B 的代理方法。

本质想说明两点,普通的静态代理,也就是自己编写代理类:一个是代理类编写时的繁杂的重复,另一个是代理类ProxyClass 受到 被代理类Class 的变更的影响很大。

 

JDK动态代理的设计:

  • 供自定义方法模板:因为通常代理类的所有方法体都类似,因此不再定义一个代理类,只定义一个如下的方法模板即可。Java提供了一个java.lang.reflect.InvacationHandler接口,实现该接口的invoke方法,在方法体中写下述自定义模板。
do proxy stuff
call origin class's method like sing
do proxy stuff
  • 生成代理类:Java不是在编译时生成的类,而是在运行时生成类,Java提供了一个java.lang.reflect.Proxy类,类中有一个newInstance方法:Proxy.newInstance(类加载器ClassLoader,被代理的接口列表Class<?>[],自定义的方法模板InvocationHandler),返回一个为指定接口代理的代理对象。

 

JDK动态代理的使用:代码如下,我代理的是java.lang.Runnable接口。

package basics.proxy;


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

/**
 * @author 100101001
 * @date 12/23/2019 10:18 AM
 */
public class jdk {

    private static int a = 123;    

    public static void main(String[] args) {
        Target t =new Target();
        //运行时生成类 Proxy$0 extends Proxy implements Runnable
        Runnable a = (Runnable) Proxy.newProxyInstance(Runnable.class.getClassLoader(), new Class[]{
                Runnable.class
        }, new InvocationHandler() { //这里采用了匿名类实现接口
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("jdk proxy before method..");
                method.invoke(t, args);
                System.out.println("jdk proxy after method..");
                //Runnable接口的run方法无返回值
                return null;
            }
        });
        new Thread(a).start();
    }

    //静态内部类等效于外部类,只不过类名jdk$Target
    //能访问jdk的所有静态变量和成员
    static class Target implements Runnable{
        @Override
        public void run() {
            System.out.println("target run"+a);
        }
    }
}

运行结果:

jdk proxy before method..
target run123
jdk proxy after method..

运行局部变量:a就是代理对象$Proxy0,其内部有一个h就是InvocationHnadler,因为它是jdk的一个匿名内部类,所以取类名 jdk$1,而t也是jdk的内部类Target(定义时)对象,所以取名 jdk$Target(可以和外部Target类区分,外部通过jdk.Target来访问该类)。

动态生成的代理类:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
 
public final class Proxy0
  extends Proxy
  implements Runnable
{
  // 在静态初始化代码块中使用反射获取Method
  // 比如 m3=Class.forName(java.lang.Runnable).getMethod("run", new Class[0])
  // h是构造Proxy时,传入的InvocationHandler
  // 在run方法体中直接 this.h.invoke(this, m3, null);
  private static Method m1;
  private static Method m3;
  private static Method m2;
  private static Method m0;
  
  public ProxySubject(InvocationHandler paramInvocationHandler)
  {
    super(paramInvocationHandler);
  }
  
  public final boolean equals(Object paramObject)
  {
    try
    {
      return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }
  
  public final void run()
  {
    try
    {
      this.h.invoke(this, m3, null);
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }
  
  public final String toString()
  {
    try
    {
      return (String)this.h.invoke(this, m2, null);
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }
  
  public final int hashCode()
  {
    try
    {
      return ((Integer)this.h.invoke(this, m0, null)).intValue();
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }
  
  static
  {
    try
    {
      m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
      m3 = Class.forName("java.lang.Runnable").getMethod("run", new Class[0]);
      m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
      m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
      return;
    }
    catch (NoSuchMethodException localNoSuchMethodException)
    {
      throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
    }
    catch (ClassNotFoundException localClassNotFoundException)
    {
      throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
    }
  }
}

 

AOP: Aspect-Oriented Programming

面向切面编程的产生:在OOP(Object-Oriented Progamming)中,方法都需要做一些共同的非功能性操作,比如对访问加锁,记录调用日志,异常处理。通过继承提供共同的操作,有单继承限制。因此,AOP产生了。我们把这些公共操作一一提炼成对应的代理模板(方法),组合到一个类中,这个类被称为切面(与继承垂直共享相对的一种横向共享的概念)。比如写一个日志切面类,定义实现两个代理模板方法,分别是开始计时(调用原方法前)和结束计时(调用原方法前)。这个日志切面类,记录了方法执行时间,方便优化分析,这些使用了切面功能的方法就是切入点。切面类似之前动态代理中的实现InvocationHandler的类,切入点类似之前的动态代理中的被代理的接口中的方法。类似这样的提炼公共操作,编写切面类,定义切入点的过程就是AOP。

 

面向切面编程的应用:这一部分参考了 简书作者:糖纸疯了 的文章 006--【SpringBoot】AOP使用集锦,web应用框架往往会使用AOP实现功能模块(比如框架提供对Controller类所有方法返回值序列化这一公共操作,开发者无需自行编写),向外提供AOP工具(比如在SpringBoot中提供AOP注解,允许用户自定义切面)。

这里自定义接口日志切面效果如下。在接口执行前,记录了接口方法,接口所在类,接口参数,接口URL等信息,执行后,记录了返回值类型。

日志效果图

在SpringBoot中,自定义Aspect的方法如下。

  • Aspect注解切面类
  • 切面类内PointCut注解方法指明代理的方法
  • Before,After,AfterReturning,AfterThrowing,Around等指明切面在方法执行的流程中代做的事情
@Aspect
@Component
public class LogWebAspect {
    //统计请求的处理时间
    ThreadLocal<Long> startTime = new ThreadLocal<>();
    /**
     * 指定切点
     * 匹配 com.enzoism.controller包及其子包下的所有类的所有方法
     */
    @Pointcut("execution(public * com.enzoism.controller.*.*(..))")
    public void webLog(){
    }

    /**
     * 前置通知,方法调用前被调用
     * @param joinPoint
     */
    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint){
        System.out.println("我是前置通知!!!");
        startTime.set(System.currentTimeMillis());
        //获取目标方法的参数信息
        Object[] obj = joinPoint.getArgs();
        System.out.println("请求参数:"+obj);
        // 代理
        Signature signature = joinPoint.getSignature();
        //代理的是哪一个方法
        System.out.println("方法:"+signature.getName());
        //AOP代理类的名字
        System.out.println("方法所在包:"+signature.getDeclaringTypeName());
        //AOP代理类的类(class)信息
        signature.getDeclaringType();
        MethodSignature methodSignature = (MethodSignature) signature;
        String[] strings = methodSignature.getParameterNames();
        System.out.println("参数名:"+ Arrays.toString(strings));
        System.out.println("参数值ARGS : " + Arrays.toString(joinPoint.getArgs()));
        // 接收到请求,记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest req = attributes.getRequest();
        // 记录下请求内容
        System.out.println("请求URL : " + req.getRequestURL().toString());
        System.out.println("HTTP_METHOD : " + req.getMethod());
        System.out.println("IP : " + req.getRemoteAddr());
        System.out.println("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());

    }

    /**
     * 处理完请求返回内容
     * @param ret
     * @throws Throwable
     */
    @AfterReturning(returning = "ret", pointcut = "webLog()")
    public void doAfterReturning(Object ret) throws Throwable {
        // 处理完请求,返回内容
        System.out.println("方法的返回值 : " + ret);
    }

    /**
     * 后置异常通知
     * @param jp
     */
    @AfterThrowing("webLog()")
    public void throwss(JoinPoint jp){
        System.out.println("方法异常时执行.....");
    }

    /**
     * 后置最终通知,final增强,不管是抛出异常或者正常退出都会执行
     * @param jp
     */
    @After("webLog()")
    public void after(JoinPoint jp){
        System.out.println("方法执行时间:"+ (System.currentTimeMillis() - startTime.get()));
        System.out.println();
    }

    /**
     * 环绕通知,环绕增强,相当于MethodInterceptor
     * @param pjp
     * @return
     */
    @Around("webLog()")
    public Object arround(ProceedingJoinPoint pjp) {
        try {
            Object o =  pjp.proceed();
            return o;
        } catch (Throwable e) {
            e.printStackTrace();
            return null;
        }
    }
}

切面除了可以应用到某个包下的所有类中的所有方法,还可以指定应用于某个注解??待更新

@Aspect
@Component
public class LogAnnotationAspect {
    /**
     * 指定切点
     * 匹配 被添加LogAnnotation标注的方法
     */
    @Pointcut("@annotation(logAnnotation)")
    public void pointCut(LogAnnotation logAnnotation) {
    }

    /**
     * 环绕通知,环绕增强,相当于MethodInterceptor
     * @param pjp
     * @return
     */
    @Around("pointCut(logAnnotation)")
    public Object arround(ProceedingJoinPoint pjp, LogAnnotation logAnnotation) {
        try {
            Object o = pjp.proceed();
            System.out.println("---------------直接指定到logAnnotation位置");
            System.out.println("actionType:"+logAnnotation.actionType());
            System.out.println("controllerName:"+logAnnotation.controllerName());
            System.out.println("module:"+logAnnotation.module());
            return o;
        } catch (Throwable e) {
            e.printStackTrace();
            return null;
        }
    }
}

 

DiffusionDriveV2 (1) : 端到端自动驾驶中受强化学习约束的截断扩散建模 DiffusionDriveV2:强化学习约束的截断扩散模型在端到端自动驾驶中的应用 本文针对端到端自动驾驶中扩散模型面临的模式崩溃问题,提出DiffusionDriveV2框架。该方法通过引入强化学习约束,解决了DiffusionDrive依赖模仿学习导致的多样性与持续高质量之间的困境。主要创新包括: 采用尺度自适应乘法噪声促进广泛探索 提出锚点内GRPO管理单个锚点样本间的优势估计 设计锚点间截断GRPO整合全局视角,避免不同驾驶意图间的不当比较 实验表明,该方法在NAVSIM基准测试中达到最先进水平( 阅读详情

相关推荐

Java + Selenium + TestNg + Allure Web UI 自动化

我们知道,在Python中针对Web UI自动化有Python + Selenium + Pytest/Unittest +Allure的技术栈。那么对于Java而言,也有其独特的Web UI 自动化技术栈。相同的,我们同样的运用Selenium框架,测试报告同样运用Allure。不同的是,我们运用的语言由Python转化为了Java,测试用例管理框架从Pytest转化为了TestNG。

qq_45594960的博客 1911

面试中关于Spring AOP和代理模式的那些事

我们知道,Spring 中 AOP 是一大核心技术,也是面试中经常会被问到的问题,最近我在网上也看到很多面试题,其中和 Spring AOP 相关的就有不少,这篇文章主要来总结下相关的技术点,希望对大家有用。 0. 几个常见的问题 针对这一块的东西,一般下面几个问题面试官问的比较多: Spring AOP用的是哪种设计模式? 谈谈你对代理模式的理解? 静态代理和动态代理有什么区别? 如何实现动态...

1万+

Vue3 与 Bpmn-js:打造现代化 BPMN 流程设计器

随着业务流程的复杂化,流程设计器成为企业级应用中不可或缺的一部分。BPMN(Business Process Model and Notation)是一种标准的业务流程建模语言,广泛应用于业务流程管理。本文将介绍如何使用 Vue3 和 Bpmn-js 打造一个现代化的 BPMN 流程设计器。

九天的专栏 2113

springboot update数据_SpringCloud或SpringBoot+Mybatis-Plus利用AOP+mybatis插件实现数据操作记录及更新对比...

引文本文主要介绍如何使用Spring AOP + mybatis插件实现拦截数据库操作并根据不同需求进行数据对比分析,主要适用于系统中需要对数据操作进行记录、在更新数据时准确记录更新字段核心:AOP、mybatis插件(拦截器)、mybatis-Plus实体规范、数据对比1、相关技术简介mybatis插件:mybatis插件实际上就是官方针对4层数据操作处理预留的拦截器,使用者可以根据不同的需求进...

weixin_29513805的博客 2609

别再到处找模板了!手把手教你用Vue3+Element Plus搭建一个‘能跑起来’的管理后台原型

本文详细介绍了如何利用Vue3和Element Plus在72小时内快速搭建一个功能完整的管理后台原型。从环境准备到项目获取、依赖安装、原型定制、数据模拟以及构建优化,手把手教你打造一个可直接演示的后台系统,特别适合创业者快速验证产品逻辑。

weixin_26854555的博客 182

Hive中的四种排序方式(order by,sort by,distribute by,cluster by)使用与区别详解

在平时的Hive数仓开发工作中经常会用到排序,而Hive中支持的排序方式有四种,这里结合具体的案例详细介绍一下他们的使用与区别: order by sort by distribute by cluster by 一、order by(全局排序) 1、作用:全局排序,只有一个reducer。 order by 会对输入做全局排序,因此只有一个reducer(多个reducer无法保证全局有序),也正因为只有一个reducer,所以当输入的数据规模较大时会导致计算时间较长。   set hive.mapr

weixin_43230682的博客 1万+

代理模式和Spring的AOP(持续更新)

代理模式 代理模式为SpringAOP的底层实现,分为静态代理和动态代理 角色分析: 抽象角色:使用接口或者抽象类 真实角色:被代理的角色 代理角色:代理真实角色,代理后增加一些附属操作 客户访问代理角色的人 静态代理 用三个角色(客户、房屋中介、房东)来介绍静态代理 编写Rent(出租)接口 (抽象角色) package com.zhbit.demo01; //租房 public inter...

HONHoChi的博客 230

EZ-USB-FX3 slavefifo调试

最近使用fx3-usb-3.0调试slave fifo的传输,期间遇到许多难以理解的问题。在这里分享给大家,希望可以少走一些弯路,我自己是这样走过来的。 1,首先去官网下载原始的参考设计,并安装所提供的SDK软件:FX3SDKSetup_1.3.4.exe 2,接着把参考设计文档AN65974阅读一遍,分别创建新的SDK工程和FPGA工程。如果使用的原厂的开发板,那么可以按照文档提示,可以很顺畅的跑完整过测试。否则需要匹配自己的硬件,做针对性的更改和移植,而我走的是后一条路,于是开始了漫长的调试之路。.

YDY5659150的专栏 3630

观察者模式+AOP 代码示例

背景 当经纪人创建客户时,需要给对应的经纪人增加战报信息。在代码层面上,客源的相关类只针对客源数据表操作。而战报信息包含了多种业务统计数据,客源只是其中统计的部分数据。鉴于两者相对独立,且客源的战报信息会有所修改。因此,采用AOP+观察者模式构建代码。 代码 定义一个注解,用于AOP拦截。 /** * 战报注解 */ @Retention(RetentionPolicy.RUNTIME) @T...

weixin_34209406的博客 193

具身智能中的(VLA)算法与实践——第一讲 基础与概览

本文介绍了视觉-语言-动作(VLA)模型的基础概念及其在AI领域的重要性。VLA模型通过融合多模态数据实现具身智能,使AI系统能感知环境并执行物理动作。文章探讨了大型语言模型(LLMs)和视觉语言模型(VLMs)如何赋能具身智能,包括指令解析、场景理解和动作规划。同时提供了Python、PyTorch/TensorFlow开发环境的详细搭建指南,包含GPU配置建议和测试代码。VLA模型在机器人操作、导航、人机协作等领域具有广泛应用前景,是实现通用人工智能的关键技术。

u012133341的博客 1598

作为一名爬虫人如何实现千万级数据爬取?

爬虫门槛不高,高就高在往后余生的每一次实操都随时会让你崩溃!Bro

吴秋霖的博客 1万+

C++11 设计模式--模板方法模拟实现Java Spring AOP

目录一:背景二:具体实现三:应用 一:背景 当进行数据库更新的时候,有以下场景需要处理: 1:业务方法执行开始的时候,需要拿到数据库连接,然后开启事务。 2:若业务在某个环节抛异常,为了数据库数据的而一致性,需要回滚事务。3:若业务执行无异常,需要提交事务。 4:最后无论业务成功或者失败,都需要释放资源。 对于这个业务场景,Java Spring框架的AOP可以很方便的对业务方法做拦截处理。Java动态代理也能很方便的实现该需求。而C++没有相对应的特性。本文模仿Java AOP,基于设计模式中的模板方法,

qq_39519014的博客 923

10倍开发者的 Dify 魔法书:从零构建全栈 AI 应用

“不懂底层算法,也能开发爆款 AI 应用吗?” 答案是:绝对可以。 Dify 正在重新定义 AI 应用的开发范式——通过可视化的低代码平台,将原本需要数周的开发周期压缩到几小时。无论你是前端、后端、产品经理,还是渴望破局的独立开发者,这都是你不可错过的红利。 我们将手把手教你利用 Dify 快速接入百模大战,零代码搭建企业级知识库,并一键发布你的专属 AI 助手、智能客服和自动化工作流。 告别重复造轮子,掌握 Dify,一个人就是一支 AI 团队。现在上车,开启你的 10 倍速开发之旅!

davidwang456的专栏 681

【数据库】如何使用一款轻量级数据库SqlSugar进行批量更新,以及查看最终的Sql操作语句

最近在使用SqlSugar这个第三方ORM框架,时间久了很多用法就容易忘记,可能也是博主上了年纪有些用法忘得快,哈哈哈。 所以,AI应用的出现,绝对是我们程序员的绝佳助手,我们可以不用记住太多的太细的知识点,把基本原理和底层架构掌握好,剩下就交给AI。

小5聊的博客 3700

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

【.NET中AOP的实现方案】静态代理

Spring AOP 应该是比较出名的了,今天说的是C#里的AOP,C#的AOP实现的方式有很多种,现在就先介绍静态代理的实现方案; 模拟场景:我们在删除用户,或者更新用户的时候进行数据原始备份,这样的话需要在删除操作进行之前进行一些数据相应的操作,但是我们又不想在删除操作里面做一些与删除无关的操作,这样使用AOP就解决这个问题了;更新操作也一样。 下面是示例代码(省略引用): 1、首先是实...

Mr_Tank_ 360

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

谈谈MVC、MVVM、MVP、AOP的区别

今天我们来谈谈 MVC、MVVM、MVP和 AOP 的区别。这些概念分属不同层级:MVC/MVVM/MVP 是架构模式,用于组织代码结构;AOP 是编程范式,解决横切关注点的问题。

xyphf的博客 1168

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

AspectJ实现设计模式(一)——观察者模式

  观察者模式是GOF中所介绍的一种常用的设计模式,本文将介绍使用AspectJ利用AOP来实现观察者模式,并通过一个简单的示例说明它的用法。    以下是AOP实现观察者模式的UML图在AOP版本中,Subject和Observer接口的成员将由抽象方面ObserverProtocol实现,而其中最关键的一点是抽象pointcut stateChange,它将由具体子方面根据不同的应

starchu1981的专栏 1737

ORM数据层框架的设计热点:更新指定的列的几种设计方案

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34258838的博客 159

代理模式(Spring Aop详解)

1.1 概述 代理(Proxy)是一种设计模式, 提供了对目标对象另外的访问方式;即通过代理访问目标对象。 这样好处: 可以在目标对象实现的基础上,增强额外的功能操作。(扩展目标对象的功能)。 举例:明星(邓紫棋)ß---经纪人<-------用户 目标 (代理) 代理模式的关键点: 代理对象与目标对象。 1.2 静态代理 静态代理, 1) 代理对象,要实现与目标对象一样的接口; ...

嘉会的博客 379

AOP.jsp+MVC.jsp

实现页面的aop和mvc模式一 : aop.jsp<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <html> <head> <script type="text/javascript" src="<%=request.getContextPath() %>/scripts/jquery-1.8.3.js">

Celebrity_Senior的博客 587

Nepxion Matrix AOP框架介绍

Nepxion Matrix AOP框架介绍 Nepxion Matrix 是一个开源的AOP(面向切面编程)框架,它主要使用Java编程语言开发。该框架与Spring框架紧密集成,提供了Spring AutoProxy、Spring Registrar和Spring Import Selector三种机制的整合,具备高度的通用性、健壮性、灵活性和易用性。 项目基础介绍 Nepxion Matri...

gitblog_00299的博客 452

007 - Spring框架中都用到了哪些设计模式?

可以通过首词法来记住Spring框架使用的一些设计模式:观单模代工(含义为观察单个模特代工)。 1、观察者模式:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知,被自动更新,例如:ApplicationListener。 2、单例模式:Bean默认为单例模式。 3、模板方法模式:用来解决代码重复的问题,以 Template 结尾的类基本都是。比如:RestTemplate、JdbcmsTemplate等。 4、代理模式:Spring的AOP功能用到了JDK的.

Zebe 490

JetCache源码解析——缓存处理

在Java技术体系中,如果想要在不改变已有代码逻辑的情况下,对已有的函数进行功能增强,一般可以使用两种方式,如AOP(Aspect Oriented Programming),即面向切面编程,以及代理模式,如使用JDK 动态代理或 CGLIB 动态代理。例如Mybatis的源码中同时使用了JDK 动态代理或 CGLIB 动态代理,但是对于Mapper接口是使用JDK动态代理模式。

qq_16500963的博客 3374

AspectJ实现设计模式(一)——观察者模式 (转)

AspectJ实现设计模式(一)——观察者模式 (转)[@more@] 观察者模式是GOF中所介绍的一种常用的设计模式,本文将介绍使用ASPectJ利用AOP来实现观察者模式,并通过一个简单的示例说明它的用法。 以下是A...

cuiji1279的博客 190

AOP+注解方式记录、打印请求信息

应对场景 在一些项目中,会有这样的一个场景,对某个接口所接受到的所有请求,进行入库记录,并记载该次请求的状态(成功与否),或业务中涉及任务时,也需要对该任务进行入库记录甚至跟踪。 最简单的实现方式,是在controler层接收到请求后,解析入参并入库保存请求(任务)信息,service层处理完逻辑后再解析返回并更新任务信息。 但这只是一次顺利的请求并成功返回的场景,如果接口返回失败,或在service层的任意地方发生异常、err,都让任务的数据库更新操作很难完成。当然,应对代码抛出异常的问题,结合全局参数异

weixin_42049458的博客 921

Spring Boot AOP 拦截器链设计方案

拦截器链的核心是通过责任链模式将多个拦截器串联起来,每个拦截器负责处理特定的逻辑。在现代Java开发中,Spring Boot的AOP(面向切面编程)为开发者提供了强大的拦截能力,能够在不侵入业务代码的情况下实现日志记录、权限校验、事务管理等横切关注点。拦截器链的调用通过ReflectiveMethodInvocation实现,它会按顺序执行链中的拦截器。通过以上设计,Spring Boot AOP拦截器链能够以低耦合、高灵活性的方式满足多样化需求,成为企业级开发中不可或缺的利器。

bmjner_102的博客 212
上一篇: 【图】最小生成树{更新中}
下一篇: 【设计模式】访问者模式{更新中}
vectorX
博客等级 码龄11年 37粉丝 21原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值