springCloud微服务系列——链路跟踪第六篇——redis缓存链路跟踪器

本文介绍了如何在springCloud微服务中实现redis缓存的链路跟踪。通过动态代理的方式,模仿mybatis的interceptor机制,提供对redis操作的拦截功能。文章详细讲解了思路,包括静态代理、动态代理、mybatis的interceptor实现,并给出了具体的示例代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一、简介

二、思路

给redis操作提供定义拦截器的功能

静态代理

动态代理

mybatis的interceptor实现

仿造mybatis的interceptor

类加载

三、示例代码


一、简介

     这篇文章总结redis缓存链路跟踪器的实现

二、思路

     redis的客户端本身是没有提供拦截器的。此外,缓存操作一般也不是一个独立的方法,而是嵌入在某业务方法内部,因此也不可能用AOP来拦截。这里的思路是通过动态代理,提供一个代理类,由它来完成redis缓存操作的拦截。

给redis操作提供定义拦截器的功能

      我们准备通过动态代理来给redis操作提供定义拦截器的功能,类似于mybatis。

      我们一步一步来,先看看需要哪些储备知识。

  • 静态代理

              

      我们可以看到,有3个角色,Action为操作的接口,Operator执行真正的操作逻辑,Proxy引用了Operator的对象,它也实现了Action接口,但是它在doSomething方法中调用Operator对象的该方法,并在调用前后附加自己的逻辑。

public class Proxy implements Action {
    
    private Operator operator;

    public Proxy(Operator operator) {
         this.operator = operator;
    }

    public void doSomething() {
         preHandle();
         operator.doSomething();
         postHandle();
    }

    private void preHandle() {
         System.out.println("前置操作");
    }

    private void postHandle() {
         System.out.println("后置操作");
    }

}

      调用的时候如下

Proxy proxy = new Proxy(new Operator());
proxy.doSomething();

      静态代理有一个很大的缺点,就是需要新代理一个接口,就必须修改Proxy类,或者新增一个Proxy类。

      比如上面的例子中,我需要新代理一个Handle接口,第一种方式,我们的uml图变为如下所示

     很明显Proxy类需要实现Handle接口,并且增加成员变量handler,增加方法doHandle

     还有一种方式是新建一个Proxy类

      我们希望不用修改Proxy类的代码,也不新增一个Proxy类。这时候就需要动态代理了。

  • 动态代理

       动态代理解决了新增一个需要代理的接口,也不用修改Proxy类或者新增一个Proxy类。

       Proxy类通过反射自动得分析出了需要代理的接口,方法,实际实现类,并把这些对象作为p参数传递给了InvocationHandler接口的实现类的invoke方法。

       示例代码如下

public class ActionProxy implements InvocationHandler {

   @Override
   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      preHandle();
      Object result = method.invoke(target, args);
      postHandle();
      return result;
   }

   private void preHandle() {
      System.out.println("前置操作");
   }

   private void postHandle() {
      System.out.println("前置操作");
   }

}

 

Action action = 
 Proxy.newProxyInstance(
    this.getClass().getClassLoader(),
    Action,
    new Operator());

action.doSomething();

       这样的话,新增一个需要被代理的接口,只需要在调用的时候修改Proxy.newProxyInstance传递的参数即可,不需要修改Proxy类的代码,或者新增一个Proxy类。

  • mybatis的interceptor实现

        mybatis的interceptor的实现就是通过动态代理实现的,我们来看看它是怎么实现的吧

        1、启动的时候通过解析配置文件,实例化interceptor,并保存下来

        

        其中紫色代表类,绿色代表方法,蓝色代表方法中的关键代码

        XMLConfigBuilder从xml中解析出ingerceptor的类名,并通过反射将其实例化,最后保存到Configuration的interceptorChain成员变量中。

private void pluginElement(XNode parent) throws Exception {
    if (parent != null) {
      for (XNode child : parent.getChildren()) {
        String interceptor = child.getStringAttribute("interceptor");
        Properties properties = child.getChildrenAsProperties();
        Interceptor interceptorInstance = (Interceptor) resolveClass(interceptor).newInstance();
        interceptorInstance.setProperties(properties);
        configuration.addInterceptor(interceptorInstance);
      }
    }
  }

         2、执行sql操作的时候使用动态代理,代理如下接口,Executor,ParameterHandler,ResultHandler,StatementHandler     

           其中紫色代表类,绿色代表方法,蓝色代表方法中的关键代码

           在执行sql操作之前,会调用newE

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值