源码解读系列-spring源码(十四)- 创建 AOP 代理的解析II

代码块11:new InstantiationModelAwarePointcutAdvisorImpl
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
                                                  Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
                                                  MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
    // 1.简单的将信息封装在类的实例中
    this.declaredPointcut = declaredPointcut;
    this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
    this.methodName = aspectJAdviceMethod.getName();
    this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
    // aspectJAdviceMethod保存的是我们用来进行逻辑增强的方法(@Around、@After等修饰的方法)
    this.aspectJAdviceMethod = aspectJAdviceMethod;
    this.aspectJAdvisorFactory = aspectJAdvisorFactory;
    this.aspectInstanceFactory = aspectInstanceFactory;
    this.declarationOrder = declarationOrder;
    this.aspectName = aspectName;
    // 2.是否需要延迟实例化
    if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
        // Static part of the pointcut is a lazy type.
        Pointcut preInstantiationPointcut = Pointcuts.union(
                aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
 
        // Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
        // If it's not a dynamic pointcut, it may be optimized out
        // by the Spring AOP infrastructure after the first evaluation.
        this.pointcut = new PerTargetInstantiationModelPointcut(
                this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
        this.lazy = true;
    } else {
        // A singleton aspect.
        this.pointcut = this.declaredPointcut;
        this.lazy = false;
        // 3.实例化增强器:根据注解中的信息初始化对应的增强器
        this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
    }
}

3.实例化增强器:根据注解中的信息初始化对应的增强器,见代码块12。

代码块12:instantiateAdvice
private Advice instantiateAdvice(AspectJExpressionPointcut pcut) {
    return this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pcut,
            this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
}
 
// ReflectiveAspectJAdvisorFactory.java
@Override
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
                        MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
    // 1.获取切面类
    Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
    // 2.校验切面类(重复校验第3次...)
    validate(candidateAspectClass);
 
    // 3.查找并返回方法的第一个AspectJ注解
    AspectJAnnotation<?> aspectJAnnotation =
            AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
    if (aspectJAnnotation == null) {
        return null;
    }
 
    // If we get here, we know we have an AspectJ method.
    // Check that it's an AspectJ-annotated class
    // 4.如果我们到这里,我们知道我们有一个AspectJ方法。检查切面类是否使用了AspectJ注解
    if (!isAspect(candidateAspectClass)) {
        throw new AopConfigException("Advice must be declared inside an aspect type: " +
                "Offending method '" + candidateAdviceMethod + "' in class [" +
                candidateAspectClass.getName() + "]");
    }
 
    if (logger.isDebugEnabled()) {
        logger.debug("Found AspectJ method: " + candidateAdviceMethod);
    }
 
    AbstractAspectJAdvice springAdvice;
 
    // 5.根据方法使用的aspectJ注解创建对应的增强器,例如最常见的@Around注解会创建AspectJAroundAdvice
    switch (aspectJAnnotation.getAnnotationType()) {
        case AtBefore:
            springAdvice = new AspectJMethodBeforeAdvice(
                    candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
            break;
        case AtAfter:
            springAdvice = new AspectJAfterAdvice(
                    candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
            break;
        case AtAfterReturning:
            springAdvice = new AspectJAfterReturningAdvice(
                    candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
            AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
            if (StringUtils.hasText(afterReturningAnnotation.returning())) {
                springAdvice.setReturningName(afterReturningAnnotation.returning());
            }
            break;
        case AtAfterThrowing:
            springAdvice = new AspectJAfterThrowingAdvice(
                    candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
            AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
            if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
                springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
            }
            break;
        case AtAround:
            springAdvice = new AspectJAroundAdvice(
                    candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
            break;
        case AtPointcut:
            if (logger.isDebugEnabled()) {
                logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
            }
            return null;
        default:
            throw new UnsupportedOperationException(
                    "Unsupported advice type on method: " + candidateAdviceMethod);
    }
 
    // Now to configure the advice...
    // 6.配置增强器
    // 切面类的name,其实就是beanName
    springAdvice.setAspectName(aspectName);
    springAdvice.setDeclarationOrder(declarationOrder);
    // 获取增强方法的参数
    String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
    if (argNames != null) {
        // 如果参数不为空,则赋值给springAdvice
        springAdvice.setArgumentNamesFromStringArray(argNames);
    }
    springAdvice.calculateArgumentBindings();
    // 最后,返回增强器
    return springAdvice;
}

代码块13:findAdvisorsThatCanApply
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
    if (candidateAdvisors.isEmpty()) {
        return candidateAdvisors;
    }
    List<Advisor> eligibleAdvisors = new LinkedList<Advisor>();
    // 1.首先处理引介增强(@DeclareParents)用的比较少可以忽略,有兴趣的参考:https://www.cnblogs.com/HigginCui/p/6322283.html
    for (Advisor candidate : candidateAdvisors) {
        if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
            eligibleAdvisors.add(candidate);
        }
    }
    boolean hasIntroductions = !eligibleAdvisors.isEmpty();
    // 2.遍历所有的candidateAdvisors
    for (Advisor candidate : candidateAdvisors) {
        // 2.1 引介增强已经处理,直接跳过
        if (candidate instanceof IntroductionAdvisor) {
            // already processed
            continue;
        }
        // 2.2 正常增强处理,判断当前bean是否可以应用于当前遍历的增强器(bean是否包含在增强器的execution指定的表达式中)
        if (canApply(candidate, clazz, hasIntroductions)) {
            eligibleAdvisors.add(candidate);
        }
    }
    return eligibleAdvisors;
}

2.2 正常增强处理,判断当前 bean 是否可以应用于当前遍历的增强器,这边表达式判断的逻辑比较复杂,可以简单的理解为:判断 bean 是否包含在增强器的 execution 指定的表达式中。

代码块14:createProxy
protected Object createProxy(
        Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
 
    if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
        AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
    }
 
    // 1.初始化ProxyFactory
    ProxyFactory proxyFactory = new ProxyFactory();
    // 从当前对象复制属性值
    proxyFactory.copyFrom(this);
 
    // 检查proxyTargetClass属性,判断对于给定的bean使用类代理还是接口代理,
    // proxyTargetClass值默认为false,可以通过proxy-target-class属性设置为true
    if (!proxyFactory.isProxyTargetClass()) {
        // 检查preserveTargetClass属性,判断beanClass是应该基于类代理还是基于接口代理
        if (shouldProxyTargetClass(beanClass, beanName)) {
            // 如果是基于类代理,则将proxyTargetClass赋值为true
            proxyFactory.setProxyTargetClass(true);
        } else {
            // 评估bean的代理接口
            evaluateProxyInterfaces(beanClass, proxyFactory);
        }
    }
    // 将拦截器封装为Advisor(advice持有者)
    Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
    // 将advisors添加到proxyFactory
    proxyFactory.addAdvisors(advisors);
    // 设置要代理的类,将targetSource赋值给proxyFactory的targetSource属性,之后可以通过该属性拿到被代理的bean的实例
    proxyFactory.setTargetSource(targetSource);
    // 自定义ProxyFactory,空方法,留给子类实现
    customizeProxyFactory(proxyFactory);
 
    // 用来控制proxyFactory被配置之后,是否还允许修改通知。默认值为false(即在代理被配置之后,不允许修改代理类的配置)
    proxyFactory.setFrozen(this.freezeProxy);
    if (advisorsPreFiltered()) {
        proxyFactory.setPreFiltered(true);
    }
 
    // 2.使用proxyFactory获取代理
    return proxyFactory.getProxy(getProxyClassLoader());
}

2.使用 proxyFactory 获取代理,见代码块15。

代码块15:getProxy
public Object getProxy(ClassLoader classLoader) {
    // 1.createAopProxy:创建AopProxy
    // 2.getProxy(classLoader):获取代理对象实例
    return createAopProxy().getProxy(classLoader);
}

1.createAopProxy:创建AopProxy,见代码块16。 2.getProxy(classLoader):获取代理对象实例,跟我们自己写的代理类似,JDK 动态代理见代码块18,CGLIB 代理见代码块19。

代码块16:createAopProxy
protected final synchronized AopProxy createAopProxy() {
    if (!this.active) {
        // 1.激活此代理配置
        activate();
    }
    // 2.创建AopProxy
    return getAopProxyFactory().createAopProxy(this);
}
 
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    // 1.判断使用JDK动态代理还是Cglib代理
    // optimize:用于控制通过cglib创建的代理是否使用激进的优化策略。除非完全了解AOP如何处理代理优化,
    // 否则不推荐使用这个配置,目前这个属性仅用于cglib代理,对jdk动态代理无效
    // proxyTargetClass:默认为false,设置为true时,强制使用cglib代理,设置方式:<aop:aspectj-autoproxy proxy-target-class="true" />
    // hasNoUserSuppliedProxyInterfaces:config是否存在代理接口或者只有SpringProxy一个接口
    if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
        // 拿到要被代理的对象的类型
        Class<?> targetClass = config.getTargetClass();
        if (targetClass == null) {
            // TargetSource无法确定目标类:代理创建需要接口或目标。
            throw new AopConfigException("TargetSource cannot determine target class: " +
                    "Either an interface or a target is required for proxy creation.");
        }
        // 要被代理的对象是接口 || targetClass是Proxy class
        // 当且仅当使用getProxyClass方法或newProxyInstance方法动态生成指定的类作为代理类时,才返回true。
        if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
            // JDK动态代理,这边的入参config(AdvisedSupport)实际上是ProxyFactory对象
            // 具体为:AbstractAutoProxyCreator中的proxyFactory.getProxy发起的调用,在ProxyCreatorSupport使用了this作为参数,
            // 调用了的本方法,这边的this就是发起调用的proxyFactory对象,而proxyFactory对象中包含了要执行的的拦截器
            return new JdkDynamicAopProxy(config);
        }
        // Cglib代理
        return new ObjenesisCglibAopProxy(config);
    } else {
        // JDK动态代理
        return new JdkDynamicAopProxy(config);
    }
}

这边创建 AopProxy 的参数 config(AdvisedSupport)实际上是代码块14中的 proxyFactory 对象。

具体为:AbstractAutoProxyCreator 中的 proxyFactory.getProxy 发起的调用,在 ProxyCreatorSupport 使用了 this 作为参数调用了本方法,这边的 this 就是发起调用的 proxyFactory对象,而 proxyFactory 对象中包含了要执行的的拦截器(Advisor)。

无论是创建 JDK 动态代理还是 CGLIB 代理,都会传入 config 参数,该参数会被保存在 advised(AdvisedSupport)变量中,见代码块17。

代码块17:JDK 动态代理、CBLIB 代理构造函数
// JdkDynamicAopProxy.java
public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
    Assert.notNull(config, "AdvisedSupport must not be null");
    if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
        throw new AopConfigException("No advisors and no TargetSource specified");
    }
    // config赋值给advised
    this.advised = config;
}
 
// ObjenesisCglibAopProxy.java
public ObjenesisCglibAopProxy(AdvisedSupport config) {
    super(config);
}
 
// CglibAopProxy.java
public CglibAopProxy(AdvisedSupport config) throws AopConfigException {
    Assert.notNull(config, "AdvisedSupport must not be null");
    if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
        throw new AopConfigException("No advisors and no TargetSource specified");
    }
    this.advised = config;
    this.advisedDispatcher = new AdvisedDispatcher(this.advised);
}
代码块18:JdkDynamicAopProxy#getProxy
@Override
public Object getProxy(ClassLoader classLoader) {
    if (logger.isDebugEnabled()) {
        logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
    }
    // 1.拿到要被代理对象的所有接口
    Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
    findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
    // 2.通过classLoader、接口、InvocationHandler实现类,来获取到代理对象
    return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

最终,通过 JDK 动态代理的类被调用时,会走到 JdkDynamicAopProxy#invoke 方法。

代码块19:CglibAopProxy#getProxy
@Override
public Object getProxy(ClassLoader classLoader) {
    if (logger.isDebugEnabled()) {
        logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());
    }
 
    try {
        // 1.拿到要代理目标类
        Class<?> rootClass = this.advised.getTargetClass();
        Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
 
        // proxySuperClass默认为rootClass
        Class<?> proxySuperClass = rootClass;
        if (ClassUtils.isCglibProxyClass(rootClass)) {
            // 如果rootClass是被Cglib代理过的,获取rootClass的父类作为proxySuperClass
            proxySuperClass = rootClass.getSuperclass();
            Class<?>[] additionalInterfaces = rootClass.getInterfaces();
            for (Class<?> additionalInterface : additionalInterfaces) {
                // 将父类的接口也添加到advised的interfaces属性
                this.advised.addInterface(additionalInterface);
            }
        }
 
        // Validate the class, writing log messages as necessary.
        // 2.校验proxySuperClass,主要是校验方法是否用final修饰、跨ClassLoader的包可见方法,如果有将警告写入日志
        validateClassIfNecessary(proxySuperClass, classLoader);
 
        // Configure CGLIB Enhancer...
        // 3.创建和配置Cglib Enhancer
        Enhancer enhancer = createEnhancer();
        if (classLoader != null) {
            enhancer.setClassLoader(classLoader);
            if (classLoader instanceof SmartClassLoader &&
                    ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
                enhancer.setUseCache(false);
            }
        }
        // superclass为被代理的目标类proxySuperClass,通过名字可以看出,生成的代理类实际上是继承了被代理类
        enhancer.setSuperclass(proxySuperClass);
        enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
        enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
        enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
 
        // 4.获取所有要回调的拦截器
        Callback[] callbacks = getCallbacks(rootClass);
        Class<?>[] types = new Class<?>[callbacks.length];
        for (int x = 0; x < types.length; x++) {
            types[x] = callbacks[x].getClass();
        }
        // fixedInterceptorMap only populated at this point, after getCallbacks call above
        // 在上面调用getCallbacks之后,此时仅填充fixedInterceptorMap
        enhancer.setCallbackFilter(new ProxyCallbackFilter(
                this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
        enhancer.setCallbackTypes(types);
 
        // Generate the proxy class and create a proxy instance.
        // 5.生成代理类并创建代理实例,返回代理实例
        return createProxyClassAndInstance(enhancer, callbacks);
    } catch (CodeGenerationException ex) {
        throw new AopConfigException("Could not generate CGLIB subclass of class [" +
                this.advised.getTargetClass() + "]: " +
                "Common causes of this problem include using a final class or a non-visible class",
                ex);
    } catch (IllegalArgumentException ex) {
        throw new AopConfigException("Could not generate CGLIB subclass of class [" +
                this.advised.getTargetClass() + "]: " +
                "Common causes of this problem include using a final class or a non-visible class",
                ex);
    } catch (Throwable ex) {
        // TargetSource.getTarget() failed
        throw new AopConfigException("Unexpected AOP exception", ex);
    }
}

4.获取所有要回调的拦截器,见代码块20。

代码块20:getCallbacks
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
    // Parameters used for optimization choices...
    // 1.用于优化选择的参数
    boolean exposeProxy = this.advised.isExposeProxy();
    boolean isFrozen = this.advised.isFrozen();
    boolean isStatic = this.advised.getTargetSource().isStatic();
 
    // Choose an "aop" interceptor (used for AOP calls).
    // 2.使用AdvisedSupport作为参数,创建一个DynamicAdvisedInterceptor(“aop”拦截器,用于AOP调用)
    // this.advised就是之前创建CglibAopProxy时传进来的ProxyFactory(ProxyCreatorSupport子类)
    Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
 
    // Choose a "straight to target" interceptor. (used for calls that are
    // unadvised but can return this). May be required to expose the proxy.
    Callback targetInterceptor;
    if (exposeProxy) {
        targetInterceptor = isStatic ?
                new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
                new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource());
    } else {
        targetInterceptor = isStatic ?
                new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
                new DynamicUnadvisedInterceptor(this.advised.getTargetSource());
    }
 
    // Choose a "direct to target" dispatcher (used for
    // unadvised calls to static targets that cannot return this).
    Callback targetDispatcher = isStatic ?
            new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp();
 
    // 3.将aop拦截器添加到mainCallbacks中
    Callback[] mainCallbacks = new Callback[]{
            aopInterceptor,  // for normal advice aop拦截器,因此当代理类被执行时,会走到该拦截器中
            targetInterceptor,  // invoke target without considering advice, if optimized
            new SerializableNoOp(),  // no override for methods mapped to this
            targetDispatcher, this.advisedDispatcher,
            new EqualsInterceptor(this.advised),    // 针对equals方法的拦截器
            new HashCodeInterceptor(this.advised)   // 针对hashcode方法的拦截器
    };
 
    Callback[] callbacks;
 
    // If the target is a static one and the advice chain is frozen,
    // then we can make some optimizations by sending the AOP calls
    // direct to the target using the fixed chain for that method.
    if (isStatic && isFrozen) {
        Method[] methods = rootClass.getMethods();
        Callback[] fixedCallbacks = new Callback[methods.length];
        this.fixedInterceptorMap = new HashMap<String, Integer>(methods.length);
 
        // TODO: small memory optimization here (can skip creation for methods with no advice)
        for (int x = 0; x < methods.length; x++) {
            List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass);
            fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
                    chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
            this.fixedInterceptorMap.put(methods[x].toString(), x);
        }
 
        // Now copy both the callbacks from mainCallbacks
        // and fixedCallbacks into the callbacks array.
        callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
        System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
        System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
        this.fixedInterceptorOffset = mainCallbacks.length;
    } else {
        callbacks = mainCallbacks;
    }
    return callbacks;
}

最终,通过 CGLIB 代理的类被调用时,会走到 DynamicAdvisedInterceptor#intercept 方法

总结

至此,创建 AOP 代理对象完成

  • 24
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值