多层代理模式解析Invocation

场景

试想一下,在另一种场景下看,需要使用JDK代理模式对最终目标对象实现增强。

例如,有一个目标对象A,框架需要提供一种能力,来实现对A的增强,所谓的增强,就是可以在执行A之前做一些事,执行A之后做一些事。这就是增强。

增强的实现:

  1. 过滤器链的思想

  2. SpringMVC拦截器思想,MVC的拦截器思想,总体来说不是一个链式执行的过程,虽然效果和调用栈一个样,但是在代码底层执行时不是嵌套增强,而是串行增强。

  3. 代理增强。

场景;

有一个目标对象A,实现AI接口

插件提供一个接口Advice,实现了Advice接口的类可以动态对A对象实现嵌套式增强,多个增强可以指定顺序、需使用代理模式实现。

复制代码
    Advice1
        Advice2
            Target... 嵌套式调用,再每一个增强中调用下一个增强。

    既然是这种设计,那么肯定有一个地方,将这个嵌套逻辑代码给组装起来,并且每一个增强器都可以直接或者间接调用到下一个增强器。
    也就是框架需要具备这种能力。

  设计思想:既然是基于接口调用实现增强,那么需要使用JDK动态代理对代理对象生成多种代理。每一层代理增强都是嵌套实现前后置增强。而且这个增强还得靠用户控制。
        基于原始对象生成代理对象后,这个代理对象获取接口也是生成这个代理对象时的实现接口。
代码实现
java 复制代码
public interface TargetInterface {

    public void doTarget();

}
java 复制代码
public class TargetObject implements TargetInterface {

    public void doTarget() {
        System.out.println("目标对象执行");
    }

}
java 复制代码
public interface Advice {

    /*
         给每一个增强器设置下一个增强器调用栈
     */
    public Object doAdvice(TargetInvoke targetInvoke) throws Throwable;

}
java 复制代码
@Data
@AllArgsConstructor
@NoArgsConstructor
public class TargetInvoke {

    //下一个增强对象
    private Object nextAdvice;

    //增强的方法
    private Method method;

    //调用方法的参数
    private Object[] args;

    /**
     * 下一个实现,分析
        Proxy.invoke,
            A
                B
                    C
        很明显,A对象需要获取B对象的引用
                而B对象需要获取C对象引用,本质上其实是获取下一个增强的处理。
     */
    public Object invoke() throws Exception {
        return method.invoke(nextAdvice,args);
    }

}
java 复制代码
public class LogAdvice implements Advice {
    @Override
    public Object doAdvice(TargetInvoke targetInvoke) throws Throwable {
        System.out.println("log advice before");
        Object res = targetInvoke.invoke();
        System.out.println("log advice after");
        return res;
    }
}
java 复制代码
public class AuthAdvice implements Advice {
    @Override
    public Object doAdvice(TargetInvoke targetInvoke) throws Throwable {
        System.out.println("auth advice before");
        Object res = targetInvoke.invoke();
        System.out.println("auth advice after");
        return res;
    }
}
java 复制代码
public class ProxyUtil {


    public static TargetInterface getProxy(TargetInterface target, Advice advice) {
        return (TargetInterface) Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                (proxy,method,args) -> {
                    //执行第一个增强,同时需要给这个增强设置下一个增强。
                    TargetInvoke targetInvoke = new TargetInvoke(target,method,args);
                    Object res = advice.doAdvice(targetInvoke);
                    return res;
                }
        );

    }
}
java 复制代码
public class Test {

    public static void main(String[] args) {

        TargetInterface targetObject = new TargetObject();

        List<Advice> adviceList = Arrays.asList(
                new AuthAdvice(),
                new LogAdvice()
        );

        //循环增强,使用每一个增强器创建代理对象,实现层层包装。
        for (Advice advice : adviceList) {
            //这里通过多层循环,使得代理层级层层封装
            targetObject = ProxyUtil.getProxy(targetObject,advice);

        }

        targetObject.doTarget();

    }

}
相关推荐
语戚1 天前
深入浅出 AOP:织入时机、JDK 动态代理与 CGLIB 原理及 Spring 选择策略
java·开发语言·spring·jdk·代理模式·aop·动态代理
NGC_66112 天前
静态代理和动态代理
代理模式
不光头强2 天前
代理模式实现,静态,动态
代理模式
逆境不可逃2 天前
【从零入门23种设计模式12】结构型之代理模式(Spring AOP + 自定义注解 + 切面的实战)
设计模式·代理模式
一碗烈酒3 天前
【使用Python临时搭建代理转发服务,内网穿透】
python·测试工具·代理模式
tsyjjOvO3 天前
代理模式详解:静态代理、JDK 动态代理、CGLIB 动态代理
java·开发语言·代理模式
柒.梧.17 天前
Java代理模式精讲:静态代理+JDK动态代理
java·开发语言·代理模式
Forget_855018 天前
RHEL——HAProxy模式
代理模式
mjhcsp21 天前
C++ 树形 DP解析
开发语言·c++·动态规划·代理模式
不想看见40421 天前
House Robber 基本动态规划:一维--力扣101算法题解笔记
笔记·算法·leetcode·代理模式