美文网首页js css html
AOP基础——JdkDynamicAopProxy

AOP基础——JdkDynamicAopProxy

作者: 王侦 | 来源:发表于2022-12-12 19:00 被阅读0次

    1.示例代码

    public class Main {
        public static void main(String[] args) {
            //1. 创建被代理对象
            Cat cat = new Cat();
            System.out.println("--------------------");
    
            //2. 创建Spring 代理工厂对象 ProxyFactory
            //   ProxyFactory 是Config + Factory 的存在,持有Aop操作所有的生产资料
            ProxyFactory proxyFactory = new ProxyFactory(cat);
    
            //3. 添加方法拦截器
            MyPointcut pointcut = new MyPointcut();
            proxyFactory.addAdvisor(new DefaultPointcutAdvisor(pointcut, new MethodInterceptor01()));
            proxyFactory.addAdvisor(new DefaultPointcutAdvisor(pointcut, new MethodInterceptor02()));
    
            //4. 获取代理对象
            Animal proxy = (Animal) proxyFactory.getProxy();
    
            proxy.eat();
            System.out.println("--------------------");
            proxy.go();
        }
    }
    

    结果,只有eat()方法被加强了:

    --------------------
    methodInterceptor01 begin
    MethodInterceptor02 begin
    猫猫 吃 猫粮!
    MethodInterceptor02 end
    methodInterceptor01 end
    --------------------
    猫猫 跑跑~!
    

    切点:

    • 1)匹配所有类
    • 2)匹配eat()方法
    public class MyPointcut implements Pointcut {
        @Override
        public ClassFilter getClassFilter() {
            return new ClassFilter() {
                @Override
                public boolean matches(Class<?> clazz) {
                    return true;
                }
            };
        }
    
        @Override
        public MethodMatcher getMethodMatcher() {
    
            return new MethodMatcher() {
                @Override
                public boolean matches(Method method, Class<?> targetClass) {
                    if(method.getName().equals("eat")) {
                        return true;
                    }
                    return false;
                }
    
                @Override
                public boolean isRuntime() {
                    return false;
                }
    
                @Override
                public boolean matches(Method method, Class<?> targetClass, Object... args) {
                    return false;
                }
            };
        }
    }
    

    2.ProxyFactory#getProxy()

        public Object getProxy() {
            //主要分析 JdkDynamicAopProxy, 假设 createAopProxy 返回的就是 JdkDynamicAopProxy
            return createAopProxy().getProxy();
        }
    

    2.1 ProxyCreatorSupport#createAopProxy

        protected final synchronized AopProxy createAopProxy() {
            if (!this.active) {
                activate();
            }
            return getAopProxyFactory().createAopProxy(this);
        }
    
        /**
         * config 就是我们的ProxyFactory对象,咱们说过 ProxyFactory
         * 它是一个配置管理对象,保存着 创建 代理对象所有的生产资料呢。
         */
        @Override
        public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
            //条件一:config.isOptimize()   暂且不管
            //条件二:config.isProxyTargetClass()  true 强制使用cglib 动态代理
            //条件三:hasNoUserSuppliedProxyInterfaces(config)
            // 说明被代理对象 没有实现任何接口,没有办法使用JDK动态代理,只能使用cglib动态代理
            if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
                Class<?> targetClass = config.getTargetClass();
                if (targetClass == null) {
                    throw new AopConfigException("TargetSource cannot determine target class: " +
                            "Either an interface or a target is required for proxy creation.");
                }
                //条件成立:说明targetClass是接口 或者 已经是被代理过的类型了,只能使用Jdk动态代理
                if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
                    return new JdkDynamicAopProxy(config);
                }
                return new ObjenesisCglibAopProxy(config);
            }
            else {
                //执行到else 什么情况?   targetClass 是实现了接口情况下,
                // 会走这个分支!咱们大多数情况都是 面向接口 编程,所以主要分析 JdkDynamicAopProxy
                return new JdkDynamicAopProxy(config);
            }
        }
    

    2.2 JdkDynamicAopProxy#getProxy()

        @Override
        public Object getProxy() {
            return getProxy(ClassUtils.getDefaultClassLoader());
        }
    
        @Override
        public Object getProxy(@Nullable ClassLoader classLoader) {
            if (logger.isTraceEnabled()) {
                logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
            }
            // 获取需要代理的接口数组
            Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
            // 查找当前所有的需要代理的接口,看看 是否有 
            // equals 方法 和 hashcode 方法,如果有,就打个标记。
            findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
            // classLoader :类加载器
            // proxiedInterfaces :生成的代理类 需要 实现的接口集合
            // this? : JdkDynamicAopProxy   该类 实现了 InvocationHandler 接口
            // 该方法最终会返回一个 代理类 对象。
            return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
        }
    

    生成的代理类类似于下面所示:

    public final class $proxy0 extends Proxy implements Animal {
        private static Method m1;
        private static Method m3;
        private static Method m2;
        private static Method m0;
    
        public $proxy0(InvocationHandler var1) throws  {
            super(var1);
        }
    
        public final boolean equals(Object var1) throws  {
            try {
                return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
            } catch (RuntimeException | Error var3) {
                throw var3;
            } catch (Throwable var4) {
                throw new UndeclaredThrowableException(var4);
            }
        }
    
        public final void eat() throws  {
            try {
                super.h.invoke(this, m3, (Object[])null);
            } catch (RuntimeException | Error var2) {
                throw var2;
            } catch (Throwable var3) {
                throw new UndeclaredThrowableException(var3);
            }
        }
    

    所有方法最后都经由InvocationHandler#invoke进行处理

    3.调用流程JdkDynamicAopProxy#invoke

        /**
         * Implementation of {@code InvocationHandler.invoke}.
         * <p>Callers will see exactly the exception thrown by the target,
         * unless a hook method throws an exception.
         *   * @param proxy 代理对象
         *   * @param method 目标对象的方法
         *   * @param args 目标对象方法对应的参数
         */
        @Override
        @Nullable
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            Object oldProxy = null;
            boolean setProxyContext = false;
    
            // 获取到创建ProxyFactory时 提供的 target
            TargetSource targetSource = this.advised.targetSource;
            // 真正的target 的一个引用
            Object target = null;
    
            try {
                // 条件成立,说明代理类实现的哪些接口 没有定义equals方法,
                // 并且当前method 是 equals方法的话,就使用JdkDynamicAopProxy 提供的 equals方法。
                if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
                    // The target does not implement the equals(Object) method itself.
                    return equals(args[0]);
                }
                // 条件成立,说明代理类实现的哪些接口 没有定义hashCode方法,
                // 并且当前method 是 hashCode方法的话,就使用JdkDynamicAopProxy 提供的 equals方法。
                else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
                    // The target does not implement the hashCode() method itself.
                    return hashCode();
                }
                else if (method.getDeclaringClass() == DecoratingProxy.class) {
                    // There is only getDecoratedClass() declared -> dispatch to proxy config.
                    return AopProxyUtils.ultimateTargetClass(this.advised);
                }
                else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
                        method.getDeclaringClass().isAssignableFrom(Advised.class)) {
                    // Service invocations on ProxyConfig with the proxy config...
                    return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
                }
    
                // 保存返回值
                Object retVal;
    
                //this.advised.exposeProxy 如果是true,
                // 就要把当前这个代理对象,暴漏 到Aop上下文内。
                if (this.advised.exposeProxy) {
                    // Make invocation available if necessary.
                    oldProxy = AopContext.setCurrentProxy(proxy);
                    setProxyContext = true;
                }
    
                // Get as late as possible to minimize the time we "own" the target,
                // in case it comes from a pool.
                // 根据targetSource拿到真正的目标对象
                target = targetSource.getTarget();
                // 获取到目标对象的 class
                Class<?> targetClass = (target != null ? target.getClass() : null);
    
                // Get the interception chain for this method.
                // 其实 这里是最关键的地方,查找适合该方法的 所有方法拦截器。
                List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
    
                // Check whether we have any advice. If we don't, we can fallback on direct
                // reflective invocation of the target, and avoid creating a MethodInvocation.
                if (chain.isEmpty()) {
                    // We can skip creating a MethodInvocation: just invoke the target directly
                    // Note that the final invoker must be an InvokerInterceptor so we know it does
                    // nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
                    Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
                    // 直接调用目标对象的目标方法。
                    retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
                }
                // 说明有匹配当前method的方法拦截器,所以要做增强处理了。
                else {
                    // We need to create a method invocation...
                    MethodInvocation invocation =
                            new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
                    // Proceed to the joinpoint through the interceptor chain.
                    // 核心!注释 :ReflectiveMethodInvocation
                    retVal = invocation.proceed();
                }
    
                // Massage return value if necessary.
                // 方法 返回值类型
                Class<?> returnType = method.getReturnType();
                // 如果目标方法 返回 目标对象,这里 做个替换,返回 代理对象。
                if (retVal != null && retVal == target &&
                        returnType != Object.class && returnType.isInstance(proxy) &&
                        !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
                    // Special case: it returned "this" and the return type of the method
                    // is type-compatible. Note that we can't help if the target sets
                    // a reference to itself in another returned object.
                    retVal = proxy;
                }
                else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
                    throw new AopInvocationException(
                            "Null return value from advice does not match primitive return type for: " + method);
                }
                return retVal;
            }
            finally {
                if (target != null && !targetSource.isStatic()) {
                    // Must have come from TargetSource.
                    targetSource.releaseTarget(target);
                }
                if (setProxyContext) {
                    // 将 上次设置的proxy 再次 设置回去到 AopContext中。
                    // 因为当前代理对象的方法已经完事了,需要回到再上一层逻辑了,
                    // 这里是一个恢复现场的逻辑。
                    // Restore old proxy.
                    AopContext.setCurrentProxy(oldProxy);
                }
            }
        }
    
    

    3.1获取目标方法的拦截器

        public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
            MethodCacheKey cacheKey = new MethodCacheKey(method);
            List<Object> cached = this.methodCache.get(cacheKey);
            if (cached == null) {
                cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
                        this, method, targetClass);
                this.methodCache.put(cacheKey, cached);
            }
            return cached;
        }
    

    DefaultAdvisorChainFactory#getInterceptorsAndDynamicInterceptionAdvice

        /**
         * 该方法的目的,就是查找出来适合当前方法 增强!
         * @param config ProxyFactory,它掌握着AOP的所有资料呢
         * @param method 目标对象的方法
         * @param targetClass 目标对象的类型
         */
        @Override
        public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
                Advised config, Method method, @Nullable Class<?> targetClass) {
    
            // This is somewhat tricky... We have to process introductions first,
            // but we need to preserve order in the ultimate list.
            //AdvisorAdapterRegistry 接口有两个作用,一个作用是
            // 可以向里面注册 AdvisorAdapter 适配器
            // 适配器目的:1. 将非Advisor 类型的 增强,包装成为Advisor
            //           2. 将Advisor 类型的增强 提取出来对应 MethodInterceptor
            AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
            // 获取出来 ProxyFactory 内部 持有的 增强信息
            // 1. addAdvice()
            // 2. AddAdvisor()  最终 在ProxyFactory 内 都会包装成 Advisor 的。
            Advisor[] advisors = config.getAdvisors();
            List<Object> interceptorList = new ArrayList<>(advisors.length);
            // 真实的目标对象类型
            Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
            Boolean hasIntroductions = null;
    
            for (Advisor advisor : advisors) {
                //条件成立:说明当前advisor是包含 切点 信息的,
                // 所以 这个if内部的逻辑,就是做匹配算法。
                if (advisor instanceof PointcutAdvisor) {
                    // Add it conditionally.
                    // 转换成 可以获取到切点信息的接口。
                    PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
                    // 条件二:成立,说明当前被代理对象的class 匹配 
                    // 当前 Advisor 成功,这一步 只是class 匹配成功。
                    if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
                        // 获取 切点信息 的 方法匹配器
                        MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
                        boolean match;
                        if (mm instanceof IntroductionAwareMethodMatcher) {
                            if (hasIntroductions == null) {
                                hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
                            }
                            match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
                        }
                        else {
                            // 如果 目标方法 匹配成功 ,那么match = true,静态匹配成功。
                            match = mm.matches(method, actualClass);
                        }
                        //静态匹配成功的话,再检查是否需要 运行时匹配。
                        if (match) {
                            // 提取出来 advisor内持有的拦截器信息
                            MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
                            // 是否运行时匹配?
                            if (mm.isRuntime()) {
                                // Creating a new object instance in the getInterceptors() method
                                // isn't a problem as we normally cache created chains.
                                for (MethodInterceptor interceptor : interceptors) {
                                    interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
                                }
                            }
                            else {
                                // 将当前advisor内部的方法拦截器 追加到 interceptorList
                                interceptorList.addAll(Arrays.asList(interceptors));
                            }
                        }
                    }
                }
                // 引介增强
                else if (advisor instanceof IntroductionAdvisor) {
                    IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
                    if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
                        Interceptor[] interceptors = registry.getInterceptors(advisor);
                        interceptorList.addAll(Arrays.asList(interceptors));
                    }
                }
                // 说明当前 Advisor 匹配全部class 全部 method
                else {
                    Interceptor[] interceptors = registry.getInterceptors(advisor);
                    interceptorList.addAll(Arrays.asList(interceptors));
                }
            }
    
            // 返回所有匹配当前method的方法拦截器
            return interceptorList;
        }
    

    DefaultAdvisorAdapterRegistry#getInterceptors

        @Override
        public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
            List<MethodInterceptor> interceptors = new ArrayList<>(3);
            Advice advice = advisor.getAdvice();
            if (advice instanceof MethodInterceptor) {
                interceptors.add((MethodInterceptor) advice);
            }
            for (AdvisorAdapter adapter : this.adapters) {
                if (adapter.supportsAdvice(advice)) {
                    interceptors.add(adapter.getInterceptor(advisor));
                }
            }
            if (interceptors.isEmpty()) {
                throw new UnknownAdviceTypeException(advisor.getAdvice());
            }
            return interceptors.toArray(new MethodInterceptor[0]);
        }
    
    public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {
    
        private final List<AdvisorAdapter> adapters = new ArrayList<>(3);
    
    
        /**
         * Create a new DefaultAdvisorAdapterRegistry, registering well-known adapters.
         */
        public DefaultAdvisorAdapterRegistry() {
            registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
            registerAdvisorAdapter(new AfterReturningAdviceAdapter());
            registerAdvisorAdapter(new ThrowsAdviceAdapter());
        }
    

    以MethodBeforeAdviceAdapter为例

    class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {
    
        @Override
        public boolean supportsAdvice(Advice advice) {
            return (advice instanceof MethodBeforeAdvice);
        }
    
        @Override
        public MethodInterceptor getInterceptor(Advisor advisor) {
            MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
            return new MethodBeforeAdviceInterceptor(advice);
        }
    
    }
    

    看看 MethodBeforeAdviceInterceptor#invoke

    public Object invoke(MethodInvocation mi) throws Throwable {
            this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
            return mi.proceed();
        }
    

    3.2 调用ReflectiveMethodInvocation#proceed

        @Override
        @Nullable
        public Object proceed() throws Throwable {
            // We start with an index of -1 and increment early.
            //条件成立:说明方法拦截器 全部都已经调用过了。
            // 接下来 需要执行 目标对象的目标方法。
            if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
                // 调用连接点
                return invokeJoinpoint();
            }
    
            // 获取下一个方法拦截器
            Object interceptorOrInterceptionAdvice =
                    this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
            // 条件成立:说明 方法拦截器 需要做 运行时匹配,很少用到运行时匹配。
            if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
                // Evaluate dynamic method matcher here: static part will already have
                // been evaluated and found to match.
                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 {
                    // Dynamic matching failed.
                    // Skip this interceptor and invoke the next in the chain.
                    return proceed();
                }
            }
            // 大部分情况,咱们都是执行else 。
            else {
                // It's an interceptor, so we just invoke it: The pointcut will have
                // been evaluated statically before this object was constructed.
                // 让当前方法拦截器执行,并且将 this 传递了 进去,this? MethodInvocation
                return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
            }
        }
    
    

    总结

    • 1)ProxyFactory是所有核心要素的汇集地,包括被代理对象、增强器Advisor
    • 2)JdkDynamicAopProxy作为InvocationHandler是所有方法调用的入口
    • 3)调用链路
      step1.JdkDynamicAopProxy#invoke
      获取匹配该方法的拦截器链;
      调用ReflectiveMethodInvocation;
      step2.ReflectiveMethodInvocation#proceed
      根据currentInterceptorIndex逐个进行调用;
      最终调用至被代理的方法;
      step3.MethodInterceptor#invoke(this),这里的this就是ReflectiveMethodInvocation
      MethodBeforeAdviceAdapter -> MethodBeforeAdviceInterceptor
      AfterReturningAdviceAdapter -> AfterReturningAdviceInterceptor
      ThrowsAdviceAdapter -> ThrowsAdviceInterceptor
      step4.最后反射调用至被代理的方法

    相关文章

      网友评论

        本文标题:AOP基础——JdkDynamicAopProxy

        本文链接:https://www.haomeiwen.com/subject/fmmfqdtx.html