AOP底子——JdkDynamicAopProxy

计算机软件开发 2024-9-16 17:59:49 47 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 beginMethodInterceptor02 begin猫猫 吃 猫粮!MethodInterceptor02 endmethodInterceptor01 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);    } 1.png     /**     * 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
      AspectJAroundAdvice、AspectJMethodBeforeAdvice、AspectJAfterAdvice
    step4.末了反射调用至被署理的方法
您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2024-10-19 00:21, Processed in 0.188339 second(s), 35 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表