美文网首页
Spring AOP源码解析(三)

Spring AOP源码解析(三)

作者: anyoptional | 来源:发表于2021-04-21 07:26 被阅读0次

前言

  上一篇分析AbstractAutoProxyCreator的时候留了一个悬念,本篇我们就一起来看看createProxy(...)的全流程吧。需要指出的是createProxy(...)整个流程还是比较复杂的,涉及到Advice的适配和扩展、拦截器链的初始化和安装、代理的创建等等,话不多说,我们开始吧~~

梦开始的地方

  protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
        @Nullable Object[] specificInterceptors, TargetSource targetSource) {
     // 在BeanDefinition中暴露原始的bean class
     // 因为采用jdk dynamic proxy的话,原始的类型信息会丢失
     // 进而想获取原始类型上的注解信息等就变得不可能了,因此
     // spring-aop选择暴露出原始的类型信息
     if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
        AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
     }

     // 代理给ProxyFactory执行真的的代理创建过程
     ProxyFactory proxyFactory = new ProxyFactory();
     // 上篇提过,EnableAspectJAutoProxy注解有两个属性
     // proxyTargetClass和exposeProxy,这里是将这两个
     // 配置属性同步给了ProxyFactory,这样在执行创建的过
     // 程中就能派上用场了
     proxyFactory.copyFrom(this);
     // proxyTargetClass不是唯一决定采用jdk dymanic proxy还是cglib subclassing的配置
     // 如果BeanDefinition明确设置了originalTargetClass,那么也会采用cglib subclassing策略
     if (!proxyFactory.isProxyTargetClass()) {
        if (shouldProxyTargetClass(beanClass, beanName)) {
           proxyFactory.setProxyTargetClass(true);
        }
        else {
           // 否则的话表示用户希望采用jdk dynamic proxy
           // 这样的话就得看看有哪些需要被代理的接口了
           evaluateProxyInterfaces(beanClass, proxyFactory);
        }
     }
     // 获取到Advisor数组(这一部分在上篇中有分析)
     Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
     // 告诉工厂要增强的内容
     proxyFactory.addAdvisors(advisors);
     // 告诉工厂是给谁创建代理
     proxyFactory.setTargetSource(targetSource);
     // 扩展方法
     customizeProxyFactory(proxyFactory);

     proxyFactory.setFrozen(this.freezeProxy);
     // 看看在实际创建时,能不能省略对ClassFilter的调用
     if (advisorsPreFiltered()) {
        proxyFactory.setPreFiltered(true);
     }
         // 执行代理的创建
     return proxyFactory.getProxy(getProxyClassLoader());
  }

如果选用JDK动态代理,那我们就得知道需要代理哪些接口,evaluateProxyInterfaces(...)的作用就是帮我们找出所有需要被代理的接口。

    protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
    // 找出beanClass实现的所有接口,包括父类
        Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());
        boolean hasReasonableProxyInterface = false;
        for (Class<?> ifc : targetInterfaces) {
      // InitializingBean、DisposableBean、*Aware等回调接口不再考虑范围内
      // 这些接口是由spring IoC管理的,同样的还有来自JDK的Closeable、AutoCloseable,
      // 也不被考虑为有效的代理接口;除此之外,还有一些众所周知的语言内部接口也不计入其中
            if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) &&
                    ifc.getMethods().length > 0) {
        // 不是上述描述的那些接口的话,可以认为是用户定义的、确实需要被代理的接口
                hasReasonableProxyInterface = true;
                break;
            }
        }
    // 存在可代理接口的话,同步给ProxyFactory
        if (hasReasonableProxyInterface) {
            // Must allow for introductions; can't just set interfaces to the target's interfaces only.
            for (Class<?> ifc : targetInterfaces) {
                proxyFactory.addInterface(ifc);
            }
        }
        else {
      // 没有的话只能选择cglib subclassing了
            proxyFactory.setProxyTargetClass(true);
        }
    }

至此AbstractAutoProxyCreator就分析完了,现在的重点自然是ProxyFactory,一起来看看它又是何方神圣吧。

代理的创建过程

ProxyFactory
proxy-factory.png

  ProxyFactory的代码很少,它的出现主要是为了降低对程序猿的心智要求——简化了其父类ProxyCreatorSupport的使用,因此我们就直接看ProxyCreatorSupport吧。

ProxyCreatorSupport

  可以看到ProxyCreatorSupport继承自AdvisedSupport,而AdvisedSupport又实现了Advised接口。在第一篇中我们就介绍过Advised接口,它被设计来保存AOP配置信息,比如目标对象是谁?是使用JDK动态代理还是CGLIB?如果使用JDK动态代理,需要被代理的接口有哪些?围绕目标对象的Advisor有哪些?AdvisedSupport的实现也是很简单的,就不耽误篇幅去分析了。

  作为一款设计模式泛滥的框架(bushi),spring-aop怎么能让ProxyCreatorSupport一个人偷偷把活干了呢,那必须俄罗斯套娃,继续代理给AopProxyFactory。从设计上看,ProxyCreatorSupport是一个上下文对象,它维护着AOP配置信息,并将这些配置信息交给它管理的AopProxyFactory去执行最后的创建逻辑,也可以说是职责单一化吧。

  AopProxyFactory只有一个默认实现——DefaultAopProxyFactory,核心方法如下:

    @Override
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        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.");
            }
            if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
                return new JdkDynamicAopProxy(config);
            }
            return new ObjenesisCglibAopProxy(config);
        }
        else {
            return new JdkDynamicAopProxy(config);
        }
    }

可以看到,就是一个选择JDK动态代理还是CGLib动态生成子类的过程。挑一个,我们来分析JdkDynamicAopProxy吧。

JdkDynamicAopProxy
jdp.png

  生成JDK动态代理必然要实现InvocationHandler接口,而AopProxy作为一个工厂接口,提供了获取代理入口。

    @Override
    public Object getProxy(@Nullable ClassLoader classLoader) {
        if (logger.isTraceEnabled()) {
            logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
        }
    // 除了evaluateProxyInterfaces(...)算法获取的接口外
    // Spring AOP还会添加Advised、SpringProxy和DecoratingProxy这几个代理接口
    //  Advised用于向外暴露aop配置信息
    //  SpringProxy作为标记接口,可用来检测某个对象是否是动态代理
    //  DecoratingProxy可用于获取代理的真实类型
        Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
    // 看一下被代理接口是否有定义equals和hashCode方法
        findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
    // 创建动态代理
        return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    }

接下来看看InvocationHandler是如何实现的吧。

    @Override
    @Nullable
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object oldProxy = null;
    
    // 根据exposeProxy的配置情况
    // 决定是否要向外暴露代理对象
        boolean setProxyContext = false;
        
    // 获取TargetSource
    // 对目标对象target的获取则会延迟到最后一步
        TargetSource targetSource = this.advised.targetSource;
    // 目标对象,也即被代理对象
        Object target = null;

        try {
      // 未自定义equals,转而判断代理是否equal
            if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
                return equals(args[0]);
            }
      // 未自定义hashCode,返回代理的hashCode
            else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
                return hashCode();
            }
      // DecoratingProxy只定义了一个方法#getDecoratedClass()
            else if (method.getDeclaringClass() == DecoratingProxy.class) {
                // 获取目标对象的类型
        return AopProxyUtils.ultimateTargetClass(this.advised);
            }
      // Advised接口中定义的方法
            else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
                    method.getDeclaringClass().isAssignableFrom(Advised.class)) {
                return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
            }

      // 返回值
            Object retVal;

      // 需要暴露代理对象的话
            if (this.advised.exposeProxy) {
        // 通过AopContext暴露出去
                oldProxy = AopContext.setCurrentProxy(proxy);
                setProxyContext = true;
            }

      // 接下来要执行的就是目标对象上的方法啦
            // 首先要获取目标对象
            target = targetSource.getTarget();
      // 目标对象的类型
            Class<?> targetClass = (target != null ? target.getClass() : null);

            // 获取作用在方法上的拦截器链
            List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

            // 没有任何Advice的话,直接调用原方法
            if (chain.isEmpty()) {
                Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
                retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
            }
            else {
        // 有Advice,就需要在此连接点上安装拦截器链了
        // 对应成代码,就是创建一个ReflectiveMethodInvocation对象
                MethodInvocation invocation =
                        new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
        // 通过拦截器链执行方法
        // 拦截器链内部会自动转向链中的下一个拦截器
                retVal = invocation.proceed();
            }

            Class<?> returnType = method.getReturnType();
      // 如果方法返回this,替换成代理对象
            if (retVal != null && retVal == target &&
                    returnType != Object.class && returnType.isInstance(proxy) &&
                    !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
                retVal = proxy;
            }
      // 原始类型和void不能有null值,fail fast
            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()) {
                targetSource.releaseTarget(target);
            }
      // 恢复AopContext的原内容
            if (setProxyContext) {
                AopContext.setCurrentProxy(oldProxy);
            }
        }
    }

InvocationHandler的实现中有两个需要注意的地方:

  1. 获取作用在连接点上的拦截器链——this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass)
  2. 安装拦截器链到连接点上——new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain)

拦截器链

获取作用在连接点上的拦截器链

  拦截器链的获取并不是由AdvisedSupport直接完成的,它也只是个中间商,实际是由AdvisorChainFactory代为完成的。

    @Override
    public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method,
                                                                  @Nullable Class<?> targetClass) {

    // AdvisorAdapterRegistry负责Advice的适配和扩展
        AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
    // 获取当前已有的所有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几乎都是PointcutAdvisor类型
      // 这里已经cover了90%的可能性
            if (advisor instanceof PointcutAdvisor) {
                PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
        // 1. 进行类的匹配
                if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
                    MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
                    boolean match;
          // 跳过Introduction,用得太少,不说了
                    if (mm instanceof IntroductionAwareMethodMatcher) {
                        if (hasIntroductions == null) {
                            hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
                        }
                        match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
                    }
                    else {
            // 2. 进行方法匹配
                        match = mm.matches(method, actualClass);
                    }
                    if (match) {
            // 获取隐藏在Advisor下的拦截器
            // Spring AOP是基于MethodInterceptor的
            // BeforeAdvice/AfterAdvice最终都要转换成MethodInterceptor
                        MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
            // 如果还需要运行时判断
                        if (mm.isRuntime()) {
                            // 此时是无法进行runtime match的
              // 只有在方法真正调用时才能进行
              // 当前能做的是把这些信息记录下来,这就是InterceptorAndDynamicMethodMatcher做的事
                            for (MethodInterceptor interceptor : interceptors) {
                                interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
                            }
                        }
                        else {
              // 不需要runtime match的话,此时就可以确定下来了
                            interceptorList.addAll(Arrays.asList(interceptors));
                        }
                    }
                }
            }
      // 忽略Introduction吧
            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));
                }
            }
            else {
        // 既不是PointcutAdvisor也不是IntroductionAdvisor
        // 直接加入吧,可以理解成PointcutAdvisor.getPointcut() == Pointcut.TRUE
                Interceptor[] interceptors = registry.getInterceptors(advisor);
                interceptorList.addAll(Arrays.asList(interceptors));
            }
        }

        return interceptorList;
    }
Advice的适配和扩展

  AdvisorAdapter是一个适配器接口,用来将Advice包装成MethodInterceptorAdvisorAdapterRegistry则提供了对AdvisorAdapter的管理功能。以MethodBeforeAdvice为例,一起来看看AdvisorAdapter是如何进行适配的吧。

class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {

    @Override
    public boolean supportsAdvice(Advice advice) {
    // 此适配器只对MethodBeforeAdvice有用
        return (advice instanceof MethodBeforeAdvice);
    }

    @Override
    public MethodInterceptor getInterceptor(Advisor advisor) {
        MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
    // 将MethodBeforeAdvice包装成MethodBeforeAdviceInterceptor
        return new MethodBeforeAdviceInterceptor(advice);
    }

}

public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {

  // 持有MethodBeforeAdvice作为代理
    private final MethodBeforeAdvice advice;

    public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
        Assert.notNull(advice, "Advice must not be null");
        this.advice = advice;
    }

    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
    // 在方法执行前使用增强
        this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
    // 转向链中的下一个拦截器
        return mi.proceed();
    }

}

Advice的适配是不是还挺简单的?再看看AdvisorAdapterRegistry呗。

public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {

    private final List<AdvisorAdapter> adapters = new ArrayList<>(3);

    public DefaultAdvisorAdapterRegistry() {
    // 注册内置的几个适配器,包括方法执行前、返回后和抛出异常时的拦截器
        registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
        registerAdvisorAdapter(new AfterReturningAdviceAdapter());
        registerAdvisorAdapter(new ThrowsAdviceAdapter());
    }

    /**
   * 将Advice包装成Advisor
   */
    @Override
    public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
    // 本身是Advisor,直接返回
        if (adviceObject instanceof Advisor) {
            return (Advisor) adviceObject;
        }
    // 不是Advisor还不是Advice
        if (!(adviceObject instanceof Advice)) {
            throw new UnknownAdviceTypeException(adviceObject);
        }
    // MethodInterceptor就不用适配了
        Advice advice = (Advice) adviceObject;
        if (advice instanceof MethodInterceptor) {
            return new DefaultPointcutAdvisor(advice);
        }
    // 否则的话得看看框架支不支持
        for (AdvisorAdapter adapter : this.adapters) {
            if (adapter.supportsAdvice(advice)) {
                return new DefaultPointcutAdvisor(advice);
            }
        }
        throw new UnknownAdviceTypeException(advice);
    }

  /**
   * 获取Advisor持有的MethodInterceptor
   */
    @Override
    public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
        List<MethodInterceptor> interceptors = new ArrayList<>(3);
        Advice advice = advisor.getAdvice();
    // Advice本身就是MethodInterceptor
        if (advice instanceof MethodInterceptor) {
            interceptors.add((MethodInterceptor) advice);
        }
    // Advice的实现类本身是可以实现多个Advice接口的
    // 比如一个类可以同时实现MethodBeforeAdvice/AfterReturningAdvice/MethodInterceptor
    // 因而这里不是if-else,而是if-if
        for (AdvisorAdapter adapter : this.adapters) {
      // 看看是不是某个支持的Advice
            if (adapter.supportsAdvice(advice)) {
        // 转换成MethodInterceptor
                interceptors.add(adapter.getInterceptor(advisor));
            }
        }
        if (interceptors.isEmpty()) {
            throw new UnknownAdviceTypeException(advisor.getAdvice());
        }
        return interceptors.toArray(new MethodInterceptor[0]);
    }

  /**
   * 注册适配器,除了spring内置的,我们也可以添加自定义的适配器
   */
    @Override
    public void registerAdvisorAdapter(AdvisorAdapter adapter) {
        this.adapters.add(adapter);
    }

}
安装拦截器链到连接点

  这部分的核心是ProxyMethodInvocation,它通过构造函数完成了拦截器链的安装。

    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;
    }

那么拦截器链如何工作呢?

    public Object proceed() throws Throwable {
    // currentInterceptorIndex起始值-1
    // 如果拦截器链中没有任何拦截器,直接调用目标方法
        if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
            return invokeJoinpoint();
        }

    // 否则获取拦截器链中的一个拦截器
    // currentInterceptorIndex递增,保证下次获取的是下一个拦截器
        Object interceptorOrInterceptionAdvice =
                this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
    // 前面说过InterceptorAndDynamicMethodMatcher是一个holder
    // 它持有的MethodMatcher是需要runtime match的
    // 而当前正是方法调用的时候
        if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
            InterceptorAndDynamicMethodMatcher dm =
                    (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
            Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
      // 进行runtime match
            if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
        // 匹配上的话调用拦截器,而拦截器内部又会调用 mi.proceed()
        // 这样的话就可以转到链上的下一个拦截器了,是不是很精妙?
                return dm.interceptor.invoke(this);
            }
            else {
                // 没匹配上,跳过这个拦截器转向下一个
                return proceed();
            }
        }
        else {
            // 普通的MethodInterceptor,调用它,并转向链中的下一个拦截器
            return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
        }
    }

    @Nullable
    protected Object invokeJoinpoint() throws Throwable {
        return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);
    }

后记

  至此,spring-aop整个流程就分析完了,至于掌握了原理后怎么玩出花儿来,就靠想象了。

相关文章

网友评论

      本文标题:Spring AOP源码解析(三)

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