IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Spring AOP基础组件 Joinpoint -> 正文阅读

[Java知识库]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));
    }
}
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-02-14 20:59:25  更:2022-02-14 21:01:22 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 12:56:10-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码