springAOP五个通知消息调用链的原理

以下是以项目的的形式就行运行验证五个消息的运行顺序及调用链的原理,里面主要用到了递归调用。

本篇博客先给大家展示代码,后面进行文字及图片讲解执行的顺序

一、创建java项目springAOPModule

二、创建项目包结构如下:

三、创建目标方法UserService

/**
 * 目标调用类
 */
public class UserService {

    public void login(String userName,Integer age){
        System.out.println("姓名为:"+userName+",年龄为:"+age);
    }
}

  

四、创建执行接口及方法(MethodInvocation/DefaultMethodInvacation)

1、方法执行接口:MethodInvocation

/**
 * 方法执行接口
 */
public interface MethodInvocation {
    Object process() throws InvocationTargetException, IllegalAccessException;
}

  

2、方法执行实习类:DefaultMethodInvacation

/**
 * 执行方法实现类
 */
public class DefaultMethodInvacation implements MethodInvocation {
    //5个通知集合
    private List<MethodInterceptor> chian;
    //目标对象
    private Object target;
    private Method method;// 目标方法
    private Object args[];// 目标参数
    int currentChianIndex;// 记录当前拦截器链调用指针

    public DefaultMethodInvacation(List<MethodInterceptor> chian, Object target, Method method, Object[] args) {
        this.chian = chian;
        this.target = target;
        this.method = method;
        this.args = args;
    }

    @Override
    public Object process() throws InvocationTargetException, IllegalAccessException {

        if(currentChianIndex==chian.size()){
            return method.invoke(target,args);
        }
        MethodInterceptor methodInterceptor = chian.get(currentChianIndex++);
        return methodInterceptor.invoke(this);
    }
}

  

五、创建拦截接口及方法

1、目标方法拦截接口:MethodInterceptor

/**
 * 创建方法拦截接口
 */
public interface MethodInterceptor {
    //执行通知的拦截
    Object invoke(MethodInvocation methodInvocation) throws InvocationTargetException, IllegalAccessException;
}

  2、前置通知方法

/**
 * 前置方法
 */
public class BeforInterceptorImpl implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation methodInvocation) throws InvocationTargetException, IllegalAccessException {
        System.out.println("进入前置通知");
        return  methodInvocation.process();
    }
}

  3、后置通知方法

public class AfterMethodInterceptor implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation methodInterceptor) throws InvocationTargetException, IllegalAccessException {
        Object process = methodInterceptor.process();
        System.out.println("后置通知");
        return process;
    }
}

  4、环绕通知方法

public class AroundMethodInterceptor implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation methodInvocation) throws InvocationTargetException, IllegalAccessException {
        System.out.println("环绕通知之前执行....");
        Object process = methodInvocation.process();
        System.out.println("环绕通知之后执行....");
        return process;
    }
}

  六、创建测试方法execute

public class execute {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        ArrayList<MethodInterceptor> list = new ArrayList<>();
        list.add(new BeforInterceptorImpl());
        list.add(new AfterMethodInterceptor());
        list.add(new AroundMethodInterceptor());
        UserService userService = new UserService();
        Method logingMethod = UserService.class.getMethod("login",String.class,Integer.class);
        Object[] objects ={"cyb",25};
        new DefaultMethodInvacation(list,userService,logingMethod,objects).process();
    }
}

  七、运行效果:

八、运行步骤原理解析:

启动运行时,系统运行步骤如下:

1、将前置通知、后置通知、环绕通知3个拦截方法放入集合中

2、获取目标方法

3、创建目标方法中的参数

4、通过有参构造方法将拦截方法集合、目标方法和参数传递到执行方法中并调用process处理方法

5、在process方法中,第一次获取拦截方法中第一个前置通知,并在里面继续调用process方法,此时index下标为1,获取后置拦截方法,并在该方法中继续调用process,此时又获取的是环绕通知拦截方法,再次进入环绕通知方法,打印”环绕通知之前执行。。。”语句,此时index值为:3,再次调用process方法,此时index等于集合长度,调用模板方法,则打印目标方法语句。调完后继续打印环绕方法的”环绕通知之后执行。。。”,执行完后在方法继续返回到后置方法执行打印“后置通知”语句

九、图形讲解

注意:前置方法的打印要写在方法调用之前,后置方法打印要写在调用方法之后,环绕方法打印则分别写在调用方法前后。

以上是本人对spring aop5个通知调用链原理的讲解,大家理解后可以对这进行更好的优化,若上文有不合适的欢迎各位博友讨论。转发请说明出处,本人博客主页地址为:https://home.cnblogs.com/u/chenyuanbo/

原文地址:https://www.cnblogs.com/chenyuanbo/p/11167459.html

时间: 2024-11-08 18:51:28

springAOP五个通知消息调用链的原理的相关文章

错误归因调用链

一.背景介绍 1.在微服务时代,服务与服务之间的调用关系错综复杂,某一服务出问题可能会导致整条链路雪崩. 2.微服务的请求链路长.涉及服务多.排查问题难,我们如何快速的定位到异常服务,尽快解决生产问题 3.我们保持对业界方案关注的同时,如:zipkin.skywalking.ELK等,如何结合自身项目的特点,搭建一套高可用.可扩展的错误归因系统? 目前的zipkin和ELK也存在一些问题没有解决: zipkin主要是告诉我们请求报错了,但是并不能发现运行时异常,例如:业务系统捕获了一个Excep

idou老师教你学Istio 08: 调用链埋点是否真的“零修改”?

本文将结合一个具体例子中的细节详细描述Istio调用链的原理和使用方式.并基于Istio中埋点的原理解释来说明:为了输出一个质量良好的调用链,业务程序需根据自身特点做适当的修改,即并非官方一直在说的完全无侵入的做各种治理.另外还会描述Istio当前版本中收集调用链数据可以通过Envoy和Mixer两种不同的方式. Istio一直强调其无侵入的服务治理,服务运行可观察性.即用户完全无需修改代码,就可以通过和业务容器一起部署的proxy来执行服务治理和与性能数据的收集.原文是这样描述的: Istio

spring框架学习6:spring-aop的五种通知类型

使用springaop时需要注意,如果bean对象,即service层的对象没有实现接口的话,使用spring-aop的话会报错,因此需要在service层创建接口. spring-aop的基层是基于动态代理来实现的,动态代理的实现有两种方式: 1.jdk动态代理 spring模式默认使用jdk动态代理,jdk动态代理要求目标类的对象必须实现一个接口,而且获取目标类对象的时候要做向上转型为接口. 2.cglib动态代理 cglib代理方式spring aop也支持,cglib实现动态代理的时候,

Spring-AOP的五种通知方式

AOP的五种通知方式: 前置通知:在我们执行目标方法之前运行(@Before) 后置通知:在我们目标方法运行结束之后,不管有没有异常(@After) 返回通知:在我们的目标方法正常返回值后运行(@AfterReturning) 异常通知:在我们的目标方法出现异常后运行(@AfterThrowing) 环绕通知:目标方法的调用由环绕通知决定,即你可以决定是否调用目标方法,joinPoint.procced()就是执行目标方法的代码 .环绕通知可以控制返回对象(@Around) 一.导jar包 co

从Consumer分析Dubbo调用链

入手 继上一篇不成熟的源码分析经历之后,为了搞清楚Consumer是如何与Provider通信的,于是又一言不合翻看起了源码.好,进入正题,依旧从RegistryDirectory这个核心类入手: // 这里的入参urls是所有可用的provider的url private Map<String, Invoker<T>> toInvokers(List<URL> urls) { Map<String, Invoker<T>> newUrlInvo

Linux环境编程之IPC进程间通信(五):Posix消息队列1

对于管道和FIFO来说,必须应该先有读取者存在,否则先有写入者是没有意义的.而消息队列则不同,它是一个消息链表,有足够写权限的线程可往别的队列中放置消息,有足够读权限的线程可从队列中取走消息.每个消息都是一个记录,它由发送者赋予一个优先级.在某个进程往一个队列写入消息之前,并不需要另外某个进程在该队列上等待消息的到达.消息队列是随内核的持续性,一个进程可以往某个队列写入一些消息,然后终止,再让另外一个进程在以后的某个时刻读出这些消息.这跟管道和FIFO不一样,当一个管道或FIFO的最后一次关闭时

Objective-C(十九、通知-消息发送模式之一)——iOS开发基础

结合之前的学习笔记以及参考<Objective-C编程全解(第三版)>,对Objective-C知识点进行梳理总结.知识点一直在变,只是作为参考,以苹果官方文档为准~ 十九.通知-消息发送模式之一 1.几个基本概念 (1)通知:在面向对象的程序中,有时需要将发生的时间通知给多个对象的消息发送模式: (2)通知中心:期望取得通知的对象预先向通知中心注册期望取得的通知: (3)发送:某对象向通知中心发送消息发送请求,只有注册过该通知单额对象,都可获得通知中心推送的消息: (4)观察者:消息发送目标

调用链系列(2):轻调用链实现

一.前言 宜信开源|调用链系列(1):解读UAVStack中的贪吃蛇 上篇文章分享了一下调用链的模型设计及模型时序图.相信大家通过上一篇文章对调用链有了一个整体上的了解,如:调用链是什么.能做什么及整体实现策略. 这篇文章我们继续介绍调用链的服务端信息收集以及服务间上下文传递. 二.服务端信息收集 服务端信息收集整体流程如下图所示,通过在应用容器(tomcat等)启动过程中植入切点从而实现在应用逻辑执行之前和之后对请求进行劫持. 应用逻辑执行之前:解析request中调用链信息,并初始化调用链上

微信公众号通知消息

微信公众号可以将消息交给WeixinHandler处理,如果能主动发送通知消息到手机微信就非常方便了,微信公众号的"发送模板消息"接口可以使用. 关注我的测试号,获取openid值关注时会通知openid值,手动发送"openid"也可获取openid值 调用微信通知消息接口参数为openid.text或chat.text用于指定通知消息,chat用于聊天响应消息(与发chat内容到测试号的效果一样) 使用场景: 服务器监控使用crontab定时执行监控脚本,如果指