All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.flyjingfish.android_aop_annotation.ProceedJoinPoint Maven / Gradle / Ivy

package com.flyjingfish.android_aop_annotation;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.flyjingfish.android_aop_annotation.base.OnBaseSuspendReturnListener;
import com.flyjingfish.android_aop_annotation.utils.AndroidAopBeanUtils;
import com.flyjingfish.android_aop_annotation.utils.InvokeMethod;
import com.flyjingfish.android_aop_annotation.utils.Utils;


import java.lang.reflect.Method;

/**
 * 切点相关信息类,wiki 文档使用说明
 */
public class ProceedJoinPoint {
    /**
     * wiki 文档使用说明
     */
    @Nullable
    public final Object[] args;
    @Nullable
    private final Object[] originalArgs;
    @Nullable
    public final Object target;
    @NonNull
    public final Class targetClass;
    private Method targetMethod;
    private InvokeMethod targetInvokeMethod;
    private Method originalMethod;
    private AopMethod targetAopMethod;
    private OnInvokeListener onInvokeListener;
    private boolean hasNext;
    private final int argCount;
    private final boolean isSuspend;
    private Object suspendContinuation;
    private Object methodReturnValue;

    ProceedJoinPoint(@NonNull Class targetClass, Object[] args, @Nullable Object target, boolean isSuspend) {
        this.targetClass = targetClass;
        Object[] fakeArgs;
        if (isSuspend && args != null){
            fakeArgs = new Object[args.length - 1];
            System.arraycopy(args, 0, fakeArgs, 0, args.length - 1);
            suspendContinuation = args[args.length - 1];
        }else {
            fakeArgs = args;
        }
        this.args = fakeArgs;

        this.target = target;
        this.isSuspend = isSuspend;
        if (fakeArgs != null) {
            this.originalArgs = fakeArgs.clone();
        } else {
            this.originalArgs = null;
        }
        this.argCount = fakeArgs != null ? fakeArgs.length : 0;
    }

    /**
     * 调用切点方法内代码
     *
     * @return 返回切点方法返回值 wiki 文档使用说明
     */
    @Nullable
    public Object proceed() {
        return proceed(args);
    }

    /**
     * 调用切点方法内代码
     *
     * @param args 切点方法参数数组
     * @return 返回切点方法返回值 wiki 文档使用说明
     */
    @Nullable
    public Object proceed(Object... args) {
        return realProceed(null,args);
    }

    @Nullable
    Object realProceed(OnBaseSuspendReturnListener onSuspendReturnListener, Object... args) {
        if (argCount > 0) {
            if (args == null || args.length != argCount) {
                throw new IllegalArgumentException("proceed 所参数个数不对");
            }
        }

        Object[] realArgs;
        if (isSuspend) {
            realArgs = new Object[argCount + 1];
            if (args != null){
                System.arraycopy(args, 0, realArgs, 0, args.length);
            }
            realArgs[argCount] = suspendContinuation;
        } else {
            realArgs = args;
        }

        if (realArgs != null && this.args != null){
            System.arraycopy(realArgs, 0, this.args, 0, this.args.length);
        }

        try {
            Object returnValue = null;
            setReturnListener(onSuspendReturnListener);
            if (!hasNext) {
                if (targetInvokeMethod != null) {
                    returnValue = targetInvokeMethod.invoke(target, realArgs);
                } else {
                    returnValue = targetMethod.invoke(target, realArgs);
                }
                methodReturnValue = returnValue;
            } else if (onInvokeListener != null) {
                returnValue = onInvokeListener.onInvoke();
            }

            return returnValue;
        } catch (Throwable e) {
            throw Utils.INSTANCE.getRealRuntimeException(e);
        }
    }

    private void setReturnListener(OnBaseSuspendReturnListener onSuspendReturnListener){
        if (isSuspend && onSuspendReturnListener != null && suspendContinuation != null){
            Object key1 = suspendContinuation;
            AndroidAopBeanUtils.INSTANCE.addSuspendReturnListener(key1,onSuspendReturnListener);
            try {
                Method method = suspendContinuation.getClass().getMethod("getCompletion");
                method.setAccessible(true);
                Object key2 = method.invoke(suspendContinuation);
                if (key2 != null){
                    AndroidAopBeanUtils.INSTANCE.addSuspendReturnListener(key2,onSuspendReturnListener);
                    AndroidAopBeanUtils.INSTANCE.saveReturnKey(key1,key2);
                }
            } catch (Throwable ignored) {
            }

        }
    }

    /**
     * @return 切点方法相关信息
     */
    @NonNull
    public AopMethod getTargetMethod() {
        return targetAopMethod;
    }

    void setTargetMethod(Method targetMethod) {
        this.targetMethod = targetMethod;
    }

    void setTargetMethod(InvokeMethod targetMethod) {
        this.targetInvokeMethod = targetMethod;
    }

    void setOriginalMethod(Method originalMethod) {
        this.originalMethod = originalMethod;
    }

    void setAopMethod(AopMethod aopMethod) {
        this.targetAopMethod = aopMethod;
    }

    /**
     * @return 切点方法所在对象,如果方法为静态的,此值为null
     */
    @Nullable
    public Object getTarget() {
        return target;
    }

    /**
     * @return 切点方法所在类 Class
     */
    @NonNull
    public Class getTargetClass() {
        return targetClass;
    }

    interface OnInvokeListener {
        Object onInvoke();
    }

    void setOnInvokeListener(OnInvokeListener onInvokeListener) {
        this.onInvokeListener = onInvokeListener;
    }

    void setHasNext(boolean hasNext) {
        this.hasNext = hasNext;
    }

    /**
     * 和 {@link ProceedJoinPoint#args} 相比,返回的引用地址不同,但数组里边的对象一致
     *
     * @return 最开始进入方法时的参数  wiki 文档使用说明
     */
    @Nullable
    public Object[] getOriginalArgs() {
        return originalArgs;
    }

    Object getMethodReturnValue() {
        return methodReturnValue;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy