责任链设计模式实战系列(三)

前言

  1. 这个系列主要讲优秀的开源框架对于责任链这个设计模式的运用,对于好的设计,我们关键是学习他的思想并运用在我们的编码中。

  2. 这个系列的所有代码都是我根据源码提炼之后的代码,不依赖原项目或框架,可以直接跑。

  3. 我不会讲每个具体是如何实现的,如果你觉得光看代码比较吃力,那么可以将代码复制下来,自己多运行几遍,我相信你一定能掌握,所以主打一个动手能力。

  4. 欢迎访问我的个人网站,里面有超多开源组件和项目,另外还有付费项目和博客,地址:https://openbytecode.com/

  5. 前两个小节主要介绍了 Tomcat 的 Filter 设计 和 SpringMVC 的 Interceptor 设计,本小节主要讲 Spring 中 AOP 的拦截器设计。

  6. 本系列 Github 地址:https://github.com/lijunping365/Open-Design

Spring 之 AOP 拦截器

public interface MethodInvocation {

    /**
     * Proceed to the next interceptor in the chain.
     * <p>The implementation and the semantics of this method depends
     * on the actual joinpoint type (see the children interfaces).
     * @return see the children interfaces' proceed definition
     * @throws Throwable if the joinpoint throws an exception
     */
    Object proceed() throws Throwable;

    /**
     * Get the method being called.
     * <p>This method is a friendly implementation of the
     * {@link Joinpoint#getStaticPart()} method (same result).
     * @return the method being called
     */
    Method getMethod();

    /**
     * Get the arguments as an array object.
     * It is possible to change element values within this
     * array to change the arguments.
     * @return the argument of the invocation
     */
    Object[] getArguments();

    /**
     * Return the object that holds the current joinpoint's static part.
     * <p>For instance, the target object for an invocation.
     * @return the object (can be null if the accessible object is static)
     */
    Object getThis();
}
public class BaseMethodInvocation implements MethodInvocation{

    protected Object[] arguments;

    protected final Object proxy;

    protected final Object target;

    protected final Method method;

    protected final Class<?> targetClass;

    protected final List<?> interceptors;

    /**
     * Index from 0 of the current interceptor we're invoking.
     * -1 until we invoke: then the current interceptor.
     */
    private int currentInterceptorIndex = -1;

    protected BaseMethodInvocation(Object proxy,
                                   Object target,
                                   Method method,
                                   Object[] arguments,
                                   Class<?> targetClass,
                                   List<?> interceptors) {
        this.proxy = proxy;
        this.target = target;
        this.method = BridgeMethodResolver.findBridgedMethod(method);
        this.arguments = adaptArgumentsIfNecessary(method, arguments);
        this.targetClass = targetClass;
        this.interceptors = interceptors;
    }

    @Override
    public Object proceed() throws Throwable {
        // We start with an index of -1 and increment early.
        if (this.currentInterceptorIndex == this.interceptors.size() - 1) {
            return invoke();
        }
        Object interceptor = this.interceptors.get(++this.currentInterceptorIndex);
        return ((MethodInterceptor) interceptor).invoke(this);
    }

    @Override
    public Method getMethod() {
        return this.method;
    }

    @Override
    public Object[] getArguments() {
        return this.arguments;
    }

    @Override
    public Object getThis() {
        return this.target;
    }
    /**
     * Invoke the joinpoint using reflection.
     * Subclasses can override this to use custom invocation.
     * @return the return value of the joinpoint
     * @throws Throwable if invoking the joinpoint resulted in an exception
     */
    @Nullable
    protected Object invoke() throws Throwable {
        return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);
    }

    /**
     * @since 4.2.3
     */
    static Object[] adaptArgumentsIfNecessary(Method method, @Nullable Object[] arguments) {
        //...
        return arguments;
    }
}
public class IMethodInvocation extends BaseMethodInvocation{

    private final MethodProxy methodProxy;

    public IMethodInvocation(Object proxy,
                             Object target,
                             Method method,
                             Object[] arguments,
                             Class<?> targetClass,
                             List<?> interceptors,
                             MethodProxy methodProxy) {

        super(proxy, target, method, arguments, targetClass, interceptors);

        // Only use method proxy for public methods not derived from java.lang.Object
        this.methodProxy = (Modifier.isPublic(method.getModifiers()) &&
                method.getDeclaringClass() != Object.class && !AopUtils.isEqualsMethod(method) &&
                !AopUtils.isHashCodeMethod(method) && !AopUtils.isToStringMethod(method) ?
                methodProxy : null);
    }

    @Override
    public Object proceed() throws Throwable {
        return super.proceed();
    }

    @Override
    protected Object invoke() throws Throwable {
        if (this.methodProxy != null) {
            return this.methodProxy.invoke(this.target, this.arguments);
        }
        else {
            return super.invoke();
        }
    }
}
@FunctionalInterface
public interface MethodInterceptor {

    /**
     * Implement this method to perform extra treatments before and
     * after the invocation. Polite implementations would certainly
     * like to invoke {@link Joinpoint#proceed()}.
     * @param invocation the method invocation joinpoint
     * @return the result of the call to {@link Joinpoint#proceed()};
     * might be intercepted by the interceptor
     * @throws Throwable if the interceptors or the target object
     * throws an exception
     */
    Object invoke(MethodInvocation invocation) throws Throwable;

}

测试

/**
 * 注意这里是实现我们自己的 MethodInterceptor
 *
 * @author lijunping on 2022/11/8
 */
public class FirstMethodInterceptor implements MethodInterceptor {

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("FirstMethodInterceptor .......Before");
        Object proceed = invocation.proceed();// 调用 IMethodInvocation 的 proceed 方法,形成递归调用
        System.out.println("FirstMethodInterceptor .......After");
        return proceed;
    }
}
/**
 * 注意这里是实现我们自己的 MethodInterceptor
 *
 * @author lijunping on 2022/11/8
 */
public class SecondMethodInterceptor implements MethodInterceptor {

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("SecondMethodInterceptor .......Before");
        Object proceed = invocation.proceed();// 调用 IMethodInvocation 的 proceed 方法,形成递归调用
        System.out.println("SecondMethodInterceptor .......After");
        return proceed;
    }
}
public class DemoService {

    public String test(){
        System.out.println("tttttttttttttttttttt");
        return "hello";
    }
}
/**
 * 注意这里的 MethodInterceptor 是 net.sf.cglib.proxy.MethodInterceptor
 *
 * @author lijunping on 2022/11/8
 */
public class DemoMethodInterceptor implements MethodInterceptor {

    private final Object target;
    private final List<?> chain;

    public DemoMethodInterceptor(Object target, List<Object> chain) {
        this.target = target;
        this.chain = chain;
    }

    @Override
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        // 构建调用链
        IMethodInvocation invocation = new IMethodInvocation(proxy, target, method, args, target.getClass(), chain, methodProxy);
        // 执行调用链
        return invocation.proceed();
    }
}
public class ProxyFactory {

    /**
     * 实例化动态代理对象
     * @param tClass 代理目标对象类型
     * @param <T> 代理目标对象类型泛型
     * @return 动态代理对象
     */
    public static <T> T getProxyInstance(Class<T> tClass, MethodInterceptor interceptor) {
        return getProxyInstance(tClass, tClass, interceptor);
    }

    /**
     * 实例化动态代理对象,并转换为对应接口类型
     * @param tClass 代理目标对象类型
     * @param interfaceClass 代理目标对象接口类型
     * @param <T> 代理目标对象接口类型泛型
     * @return 动态代理对象
     */
    public static <T> T getProxyInstance(Class<? extends T> tClass, Class<T> interfaceClass, MethodInterceptor interceptor) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(tClass);
        enhancer.setClassLoader(tClass.getClassLoader());
        enhancer.setCallback(interceptor); // 实现了 MethodInterceptor 接口的类
        return interfaceClass.cast(enhancer.create());
    }
}
public class ChainDemo {
    public static void main(String[] args) {
        // 创建目标对象
        DemoService demoService = new DemoService();
        // 构建拦截器链
        List<Object> chain = new ArrayList<>();
        chain.add(new FirstMethodInterceptor());
        chain.add(new SecondMethodInterceptor());
        // 创建 cglib 动态代理的 Interceptor
        DemoMethodInterceptor interceptor = new DemoMethodInterceptor(demoService, chain);
        // 获取代理对象
        DemoService proxyInstance = ProxyFactory.getProxyInstance(DemoService.class, interceptor);
        // 执行代理对象
        proxyInstance.test();
    }
}

输出结果:

FirstMethodInterceptor .......Before
SecondMethodInterceptor .......Before
tttttttttttttttttttt
SecondMethodInterceptor .......After
FirstMethodInterceptor .......After

欢迎在评论区留下你的总结

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值