Spring AOP基础组件 Joinpoint

相关阅读

简介

Joinpoint表示通用的运行时连接点;
运行时连接点是发生在静态连接点上的事件,比如方法的一次调用就是运行时连接点;可以通过getStaticPart获取连接点的静态部分;
在拦截框架的上下文中,运行时连接点是可访问的对象(方法,构造方法,字段),即连接点的静态部分,的访问的物化,被传递给注册在静态连接点上的拦截器;

源码

public interface Joinpoint {

    // 继续链中下一个拦截器
    @Nullable
    Object proceed() throws Throwable;

    // 获取持有当前连接点静态部分的对象,比如当前调用的目标对象
    // 如果可访问的对象是静态的,则返回null
    @Nullable
    Object getThis();

    // 获取连接点的静态部分(方法,构造方法,字段等)
    @Nonnull
    AccessibleObject getStaticPart();
}

实现子类

public interface Joinpoint
    public interface Invocation extends Joinpoint
        public interface ConstructorInvocation extends Invocation
        public interface MethodInvocation extends Invocation
            public interface ProxyMethodInvocation extends MethodInvocation
                public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable
                    private static class CglibMethodInvocation extends ReflectiveMethodInvocation

Invocation

简介

Invocation代表一次调用;
Invocation可以被Interceptor拦截;

核心代码

public interface Invocation extends Joinpoint {

    // 获取方法调用的参数
    @Nonnull
    Object[] getArguments();
}

ConstructorInvocation

简介

ConstructorInvocation代表构造方法的调用,在构造方法调用时提供给拦截器;
ConstructorInvocation可以被ConstructorInterceptor拦截;

核心代码

public interface ConstructorInvocation extends Invocation {

    // 获取被调用的构造方法
    @Nonnull
    Constructor<?> getConstructor();
}

MethodInvocation

简介

MethodInvocation代表方法的调用,在方法调用时提供给拦截器;
MethodInvocation可以被MethodInterceptor拦截;

核心代码

public interface MethodInvocation extends Invocation {

    // 获取被调用的方法
    @Nonnull
    Method getMethod();
}

ProxyMethodInvocation

简介

ProxyMethodInvocation支持访问通过该方法调用的代理对象;
当需要替换返回值为代理对象时,这很有用,比如方法的返回值就是目标对象本身;

核心代码

public interface ProxyMethodInvocation extends MethodInvocation {

    // 获取该方法调用的代理对象
    Object getProxy();

    // clone自身
    // 如果在proceed之前发生,则每个clone体都可以调用proceed和advice chain的剩余部分
    MethodInvocation invocableClone();

    // 带参的clone
    // 如果在proceed之前发生,则每个clone体都可以调用proceed和advice chain的剩余部分
    MethodInvocation invocableClone(Object... arguments);

    // 设置用于advice chain中后续方法调用的参数
    void setArguments(Object... arguments);

    // 设置用户属性
    void setUserAttribute(String key, @Nullable Object value);

    // 获取用户设置属性
    @Nullable
    Object getUserAttribute(String key);
}

ProxyMethodInvocation

简介

ProxyMethodInvocation支持访问通过该方法调用的代理对象;
当需要替换返回值为代理对象时,这很有用,比如方法的返回值就是目标对象本身;

核心代码

public interface ProxyMethodInvocation extends MethodInvocation {

    // 获取该方法调用的代理对象
    Object getProxy();

    // clone自身
    // 如果在proceed之前发生,则每个clone体都可以调用proceed和advice chain的剩余部分
    MethodInvocation invocableClone();

    // 带参的clone
    // 如果在proceed之前发生,则每个clone体都可以调用proceed和advice chain的剩余部分
    MethodInvocation invocableClone(Object... arguments);

    // 设置用于advice chain中后续方法调用的参数
    void setArguments(Object... arguments);

    // 设置用户属性
    void setUserAttribute(String key, @Nullable Object value);

    // 获取用户设置属性
    @Nullable
    Object getUserAttribute(String key);
}

ReflectiveMethodInvocation

简介

Spring框架的MethodInvocation实现,通过反射调用目标对象,子类可以重写invokeJoinpoint方法来实现其它的逻辑;
可以通过invocableClone克隆一次方法调用来重复执行proceed,也可以通过setUserAttribute/getUserAttribute绑定一些定制属性到方法调用;

核心代码

public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable {

    // 代理对象
    protected final Object proxy;

    // 目标对象
    @Nullable
    protected final Object target;

    // 被调用的方法
    protected final Method method;

    // 方法参数
    protected Object[] arguments;

    // 目标对象类型
    @Nullable
    private final Class<?> targetClass;

    // 用户属性
    @Nullable
    private Map<String, Object> userAttributes;

    // Advice chain
    protected final List<?> interceptorsAndDynamicMethodMatchers;

    // 当前拦截器的索引
    private int currentInterceptorIndex = -1;


    // 构造方法
    protected ReflectiveMethodInvocation(
            Object proxy, @Nullable Object target, Method method, @Nullable Object[] arguments,
            @Nullable Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers) {

        this.proxy = proxy;
        this.target = target;
        this.targetClass = targetClass;
        this.method = BridgeMethodResolver.findBridgedMethod(method);
        this.arguments = AopProxyUtils.adaptArgumentsIfNecessary(method, arguments);
        this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers;
    }

    @Override
    public final Object getProxy() {
        // 返回代理对象
        return this.proxy;
    }

    @Override
    @Nullable
    public final Object getThis() {
        // 返回目标对象
        return this.target;
    }

    @Override
    public final AccessibleObject getStaticPart() {
        // 返回调用方法
        return this.method;
    }

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

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

    @Override
    public void setArguments(Object... arguments) {
        this.arguments = arguments;
    }

    @Override
    @Nullable
    public Object proceed() throws Throwable {
        // 遍历完advice chain后,才执行连接点
        if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
            return invokeJoinpoint();
        }

        // 获取当前遍历到的Advice
        Object interceptorOrInterceptionAdvice =
                this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
        if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
            // Advice是InterceptorAndDynamicMethodMatcher
            InterceptorAndDynamicMethodMatcher dm =
                    (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
            Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
            // 方法是否动态匹配
            if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
                // 匹配则执行
                return dm.interceptor.invoke(this);
            }
            else {
                // 动态匹配失败,则跳过本次Advice,直接执行advice chain中下一个
                return proceed();
            }
        }
        else {
            // Advice是Interceptor,直接调用
            return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
        }
    }

    @Nullable
    protected Object invokeJoinpoint() throws Throwable {
        // 通过反射执行连接点
        return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);
    }

    @Override
    public MethodInvocation invocableClone() {
        Object[] cloneArguments = this.arguments;
        if (this.arguments.length > 0) {
            // 参数有效,则也需要clone
            cloneArguments = this.arguments.clone();
        }
        return invocableClone(cloneArguments);
    }

    @Override
    public MethodInvocation invocableClone(Object... arguments) {
        // Force initialization of the user attributes Map,
        // for having a shared Map reference in the clone.
        if (this.userAttributes == null) {
            this.userAttributes = new HashMap<>();
        }

        try {
            ReflectiveMethodInvocation clone = (ReflectiveMethodInvocation) clone();
            // 设置独立的方法参数
            clone.arguments = arguments;
            return clone;
        }
        catch (CloneNotSupportedException ex) {
            throw new IllegalStateException(
                    "Should be able to clone object of type [" + getClass() + "]: " + ex);
        }
    }

    @Override
    public void setUserAttribute(String key, @Nullable Object value) {
        if (value != null) {
            if (this.userAttributes == null) {
                this.userAttributes = new HashMap<>();
            }
            this.userAttributes.put(key, value);
        }
        else {
            if (this.userAttributes != null) {
                this.userAttributes.remove(key);
            }
        }
    }

    @Override
    @Nullable
    public Object getUserAttribute(String key) {
        return (this.userAttributes != null ? this.userAttributes.get(key) : null);
    }

    public Map<String, Object> getUserAttributes() {
        if (this.userAttributes == null) {
            this.userAttributes = new HashMap<>();
        }
        return this.userAttributes;
    }
}

CglibMethodInvocation

简介

AOP代理使用的MethodInvocation实现;

核心代码

private static class CglibMethodInvocation extends ReflectiveMethodInvocation {

    // 方法代理
    @Nullable
    private final MethodProxy methodProxy;

    // 构造方法
    public CglibMethodInvocation(Object proxy, @Nullable Object target, Method method,
            Object[] arguments, @Nullable Class<?> targetClass,
            List<Object> interceptorsAndDynamicMethodMatchers, MethodProxy methodProxy) {

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

        // 仅限非Object的public方法
        this.methodProxy = (isMethodProxyCompatible(method) ? methodProxy : null);
    }

    @Override
    @Nullable
    public Object proceed() throws Throwable {
        try {
            // 调用父类实现
            return super.proceed();
        }
        // 增加了异常处理
        catch (RuntimeException ex) {
            throw ex;
        }
        catch (Exception ex) {
            if (ReflectionUtils.declaresException(getMethod(), ex.getClass()) ||
                    KotlinDetector.isKotlinType(getMethod().getDeclaringClass())) {
                // Propagate original exception if declared on the target method
                // (with callers expecting it). Always propagate it for Kotlin code
                // since checked exceptions do not have to be explicitly declared there.
                throw ex;
            }
            else {
                // Checked exception thrown in the interceptor but not declared on the
                // target method signature -> apply an UndeclaredThrowableException,
                // aligned with standard JDK dynamic proxy behavior.
                throw new UndeclaredThrowableException(ex);
            }
        }
    }

    @Override
    protected Object invokeJoinpoint() throws Throwable {
        if (this.methodProxy != null) {
            try {
                // 优先直接使用目标对象执行方法,比通过反射要略微提升性能
                return this.methodProxy.invoke(this.target, this.arguments);
            }
            catch (CodeGenerationException ex) {
                logFastClassGenerationFailure(this.method);
            }
        }
        // 执行失败,则调用父类实现
        return super.invokeJoinpoint();
    }

    static boolean isMethodProxyCompatible(Method method) {
        return (Modifier.isPublic(method.getModifiers()) &&
                method.getDeclaringClass() != Object.class && !AopUtils.isEqualsMethod(method) &&
                !AopUtils.isHashCodeMethod(method) && !AopUtils.isToStringMethod(method));
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值