Spring IOC 源码解析之createBean(四)

Spring5.1.x版本,使用注解扫描的方式

接上一篇Spring IOC 源码解析之getBean(三),继续分析createBean方法。

@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
        throws BeanCreationException {

    if (logger.isTraceEnabled()) {
        logger.trace("Creating instance of bean '" + beanName + "'");
    }
    RootBeanDefinition mbdToUse = mbd;

    // Make sure bean class is actually resolved at this point, and
    // clone the bean definition in case of a dynamically resolved Class
    // which cannot be stored in the shared merged bean definition.
    // 解析bean类型
    Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
    if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
        mbdToUse = new RootBeanDefinition(mbd);
        mbdToUse.setBeanClass(resolvedClass);
    }

    // Prepare method overrides.
    try {
        mbdToUse.prepareMethodOverrides();
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                beanName, "Validation of method overrides failed", ex);
    }

    try {
        // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
        // 给InstantiationAwareBeanPostProcessor一个机会去返回一个代理对象,
        // 在doCreateBean()生成对象之前, 给用户自定义返回一个对象的机会
        Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
        if (bean != null) {
            return bean;
        }
    }
    catch (Throwable ex) {
        throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                "BeanPostProcessor before instantiation of bean failed", ex);
    }

    try {
        // 准备开始创建
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
        if (logger.isTraceEnabled()) {
            logger.trace("Finished creating instance of bean '" + beanName + "'");
        }
        return beanInstance;
    }
    catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
        // A previously detected exception with proper bean creation context already,
        // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
        throw ex;
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
                mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
    }
}

createBean方法执行完后返回的就是一个完整的bean实例。

doCreateBean

这里面就是真正去创建bean

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {

    // bean包装类
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    // 为空表示不是factoryBean
    if (instanceWrapper == null) {
        // 1、创建bean实例
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    // 创建的实例
    final Object bean = instanceWrapper.getWrappedInstance();
    Class<?> beanType = instanceWrapper.getWrappedClass();
    if (beanType != NullBean.class) {
        mbd.resolvedTargetType = beanType;
    }

    // Allow post-processors to modify the merged bean definition.
    synchronized (mbd.postProcessingLock) {
        // postProcessed字段用于表示是否已应用MergedBeanDefinitionPostProcessor,
        // 默认一开始是false
        if (!mbd.postProcessed) {
            try {
                // 2、应用后置处理器MergedBeanDefinitionPostProcessor,
                // Autowired注解正是通过此方法实现注入类型的预解析
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
            }
            catch (Throwable ex) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Post-processing of merged bean definition failed", ex);
            }
            mbd.postProcessed = true;
        }
    }

    // Eagerly cache singletons to be able to resolve circular references
    // even when triggered by lifecycle interfaces like BeanFactoryAware.
    // 3、判断是否要提前暴露该bean,必须满足 单例 && 允许循环依赖 && 该bean正在创建
    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
            isSingletonCurrentlyInCreation(beanName));
    if (earlySingletonExposure) {
        if (logger.isTraceEnabled()) {
            logger.trace("Eagerly caching bean '" + beanName +
                    "' to allow for resolving potential circular references");
        }
        // 4、提前暴露该bean的ObjectFactory,以解决循环依赖
        addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    }

    // Initialize the bean instance.
    Object exposedObject = bean;
    try {
        // 5、负责属性设值
        populateBean(beanName, mbd, instanceWrapper);
        // 6、处理 bean 初始化完成后的各种回调,比如后置处理,init方法等
        exposedObject = initializeBean(beanName, exposedObject, mbd);
    }
    catch (Throwable ex) {
        if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
            throw (BeanCreationException) ex;
        }
        else {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
        }
    }
	
    // 7、如果允许提前曝光实例,则进行循环依赖检查
    if (earlySingletonExposure) {
        // earlySingletonReference只有在当前解析的bean存在循环依赖的情况下才会不为空
        // false表示只会从一级和二级缓存中查找,如果没有循环依赖,当前bean还在三级缓存中,
        // 一二级缓存还没有该bean(如果没有循环依赖和代理的情况下,bean不会在二级缓存存在过)
        Object earlySingletonReference = getSingleton(beanName, false);
        // todo 这部分有点看不懂
        if (earlySingletonReference != null) {
            if (exposedObject == bean) {
                exposedObject = earlySingletonReference;
            }
            else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                String[] dependentBeans = getDependentBeans(beanName);
                Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
                for (String dependentBean : dependentBeans) {
                    if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                        actualDependentBeans.add(dependentBean);
                    }
                }
                if (!actualDependentBeans.isEmpty()) {
                    throw new BeanCurrentlyInCreationException(beanName,
                            "Bean with name '" + beanName + "' has been injected into other beans [" +
                            StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                            "] in its raw version as part of a circular reference, but has eventually been " +
                            "wrapped. This means that said other beans do not use the final version of the " +
                            "bean. This is often the result of over-eager type matching - consider using " +
                            "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
                }
            }
        }
    }

    // 8、注册用于销毁的bean,执行销毁操作的有三种:自定义destroy方法、
    // DisposableBean接口、DestructionAwareBeanPostProcessor
    try {
        registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }

    return exposedObject;
}

1、创建bean实例

根据策略选择一种实例化方式

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    // bean类型
    Class<?> beanClass = resolveBeanClass(mbd, beanName);
    if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
    }

    Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
    if (instanceSupplier != null) {
        return obtainFromSupplier(instanceSupplier, beanName);
    }

    // 1、如果存在工厂方法则使用工厂方法创建实例
    if (mbd.getFactoryMethodName() != null) {
        return instantiateUsingFactoryMethod(beanName, mbd, args);
    }

    // Shortcut when re-creating the same bean...
    // 重复创建相同bean处理方式,意思是多次创建prototype类型的bean
    // 这种情况下,我们可以从第一次创建知道,采用无参构造函数,还是构造函数依赖注入来完成实例化
    // 无需再做下面第4步的判断
    boolean resolved = false;
    boolean autowireNecessary = false;
    if (args == null) {
        synchronized (mbd.constructorArgumentLock) {
            // 是否缓存了已经解析的构造函数或是工厂方法
            // 如果缓存了,说明之前已经创建过实例,解析过了使用何种实例化方式
            if (mbd.resolvedConstructorOrFactoryMethod != null) {
                resolved = true;
                autowireNecessary = mbd.constructorArgumentsResolved;
            }
        }
    }
    // 之前已经解析过了,就直接判断autowireNecessary来决定使用何种方式实例化
    if (resolved) {
        if (autowireNecessary) {
            // 2、依赖注入构造方法
            return autowireConstructor(beanName, mbd, null, null);
        }
        else {
            // 3、无参构造方法
            return instantiateBean(beanName, mbd);
        }
    }

    // Candidate constructors for autowiring?
    // 4、判断是否采用有参构造方法
    Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    // 如果ctors不为空 || mbd的注入方式为AUTOWIRE_CONSTRUCTOR || mdb定义了构造函数的参数值 
    // || args不为空,则执行构造方法自动注入
    if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
            mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
        
        // 构造方法注入
        return autowireConstructor(beanName, mbd, ctors, args);
    }

    // Preferred constructors for default construction?
    ctors = mbd.getPreferredConstructors();
    if (ctors != null) {
        // 5、依赖注入构造方法
        return autowireConstructor(beanName, mbd, ctors, null);
    }

    // No special handling: simply use no-arg constructor.
    // 6、没有特殊的处理,简单的使用无参构造方法实例化
    return instantiateBean(beanName, mbd);
}

这里只对其中两种方式进行解析,也是最常用的两种方式。

先看下实例化时需要同时注入依赖的,叫作构造方法注入,也就是第4步,当使用下面这种写法时会进入第4步,实例化时需要传入一个依赖。

private final Teacher teacher;

@Autowired
public Student(Teacher teacher) {
    this.teacher = teacher;
}

先获取到@Autowired注解标注的构造方法

protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName)
    	throws BeansException {

    // 是否注册了InstantiationAwareBeanPostProcessor后置器
    if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
        // 遍历所有的bean后置器,调用其中的SmartInstantiationAwareBeanPostProcessor类型的
        // determineCandidateConstructors方法,该方法可以返回候选构造方法
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
                SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
                Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
                // 只要有一个不返回空,就不再调用了
                if (ctors != null) {
                    return ctors;
                }
            }
        }
    }
    return null;
}

这里会调用到AutowiredAnnotationBeanPostProcessor,该类继承了InstantiationAwareBeanPostProcessorAdapter,而InstantiationAwareBeanPostProcessorAdapter又实现了SmartInstantiationAwareBeanPostProcessor

public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
    	throws BeanCreationException {

    // 检查lookup,可以不关注
    if (!this.lookupMethodsChecked.contains(beanName)) {
        try {
            ReflectionUtils.doWithMethods(beanClass, method -> {
                Lookup lookup = method.getAnnotation(Lookup.class);
                if (lookup != null) {
                    Assert.state(this.beanFactory != null, "No BeanFactory available");
                    LookupOverride override = new LookupOverride(method, lookup.value());
                    try {
                        RootBeanDefinition mbd = (RootBeanDefinition) this.beanFactory.getMergedBeanDefinition(beanName);
                        mbd.getMethodOverrides().addOverride(override);
                    }
                    catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanCreationException(beanName,
                                                        "Cannot apply @Lookup to beans without corresponding bean definition");
                    }
                }
            });
        }
        catch (IllegalStateException ex) {
            throw new BeanCreationException(beanName, "Lookup method resolution failed", ex);
        }
        this.lookupMethodsChecked.add(beanName);
    }

    // 检查缓存中有没有该类的候选构造方法
    Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
    if (candidateConstructors == null) {
        // 双重检查锁
        synchronized (this.candidateConstructorsCache) {
            candidateConstructors = this.candidateConstructorsCache.get(beanClass);
            // 第一次进来肯定是空的
            if (candidateConstructors == null) {
                Constructor<?>[] rawCandidates;
                try {
                    // 得到该类的所有构造方法
                    rawCandidates = beanClass.getDeclaredConstructors();
                }
                catch (Throwable ex) {
                    throw new BeanCreationException(beanName,
                                                    "Resolution of declared constructors on bean Class [" + beanClass.getName() +
                                                    "] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
                }
                // 存放使用了@Autowired的构造方法
                List<Constructor<?>> candidates = new ArrayList<>(rawCandidates.length);
                // 存放使用了@Autowire并且require=true的构造方法
                Constructor<?> requiredConstructor = null;
                // 存放默认的构造方法
                Constructor<?> defaultConstructor = null;
                // 存放主构造方法,供Kotlin类使用,非Kotlin类这里返回空
                Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);
                int nonSyntheticConstructors = 0;
                // 遍历所有构造方法
                for (Constructor<?> candidate : rawCandidates) {
                    if (!candidate.isSynthetic()) {
                        nonSyntheticConstructors++;
                    }
                    else if (primaryConstructor != null) {
                        continue;
                    }
                    // 获取构造方法上@Autowired和@Value注解的属性
                    AnnotationAttributes ann = findAutowiredAnnotation(candidate);
                    // 没有注解属性
                    if (ann == null) {
                        // 返回原始类,一般就是本身的类,但如果是CGLIB代理类,则返回原始的类
                        Class<?> userClass = ClassUtils.getUserClass(beanClass);
                        if (userClass != beanClass) {
                            try {
                                Constructor<?> superCtor =
                                    userClass.getDeclaredConstructor(candidate.getParameterTypes());
                                ann = findAutowiredAnnotation(superCtor);
                            }
                            catch (NoSuchMethodException ex) {
                                // Simply proceed, no equivalent superclass constructor found...
                            }
                        }
                    }
                    if (ann != null) {
                        // 之前已经存在使用@Autowired(required = true)的构造函数,
                        // 则当前构造方法不能使用@Autowire注解,否则抛异常
                        // @Autowired
                        // public Student(Teacher teacher) {
                        //     this.teacher = teacher;
                        // }

                        // @Autowired // 或者@Autowired(required = false)
                        // public Student() {}
                        // 就是说上面这样是不行的
                        // 意思是如果有一个@Autowired是必须注入的,则不能再存在另一个注解@Autowired
                        if (requiredConstructor != null) {
                            throw new BeanCreationException(beanName,
                                                            "Invalid autowire-marked constructor: " + candidate +
                                                            ". Found constructor with 'required' Autowired annotation already: " +
                                                            requiredConstructor);
                        }
                        // 注解上required属性的值
                        boolean required = determineRequiredStatus(ann);
                        if (required) {
                            // 之前已经存在使用@Autowired的构造函数,
                            // 则当前构造方法不能使用@Autowired(required = true),否则抛异常
                            if (!candidates.isEmpty()) {
                                throw new BeanCreationException(beanName,
                                                                "Invalid autowire-marked constructors: " + candidates +
                                                                ". Found constructor with 'required' Autowired annotation: " +
                                                                candidate);
                            }
                            // 当前构造方法设为有@Autowired(required = true)标注的构造方法
                            requiredConstructor = candidate;
                        }
                        // 将有@Autowired注解的构造方法加到candidates中
                        candidates.add(candidate);
                    }
                    // 如果构造方法上没有@Autowired注解和方法参数,则是默认构造方法
                    else if (candidate.getParameterCount() == 0) {
                        defaultConstructor = candidate;
                    }
                }
                // 如果存在有@Autowired注解的构造方法,则将这些构造方法设置到候选构造方法
                if (!candidates.isEmpty()) {
                    // Add default constructor to list of optional constructors, as fallback.
                    if (requiredConstructor == null) {
                        // 如果没有一个@Autowired注解上的required属性是true的并且存在默认的构造方法,
                        // 则将默认的构造方法也添加进候选的
                        if (defaultConstructor != null) {
                            candidates.add(defaultConstructor);
                        }
                        else if (candidates.size() == 1 && logger.isInfoEnabled()) {
                            logger.info("Inconsistent constructor declaration on bean with name '" + beanName +
                                        "': single autowire-marked constructor flagged as optional - " +
                                        "this constructor is effectively required since there is no " +
                                        "default constructor to fall back to: " + candidates.get(0));
                        }
                    }
                    candidateConstructors = candidates.toArray(new Constructor<?>[0]);
                }
                // 下面就是不存在有@Autowired注解的构造方法的情况了
                // 只有一个构造方法并且有参数(非默认构造方法),则将这个构造方法作为候选构造方法
                else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
                    candidateConstructors = new Constructor<?>[] {rawCandidates[0]};
                }
                else if (nonSyntheticConstructors == 2 && primaryConstructor != null &&
                         defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {
                    candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor};
                }
                else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {
                    candidateConstructors = new Constructor<?>[] {primaryConstructor};
                }
                else {
                    // 否则就是返回空
                    candidateConstructors = new Constructor<?>[0];
                }
                this.candidateConstructorsCache.put(beanClass, candidateConstructors);
            }
        }
    }
    return (candidateConstructors.length > 0 ? candidateConstructors : null);
}

以上获取候选构造方法的流程说明了在一个 bean 中,只要有构造方法使用了 “@Autowired(required = true)” 或 “@Autowired”,就不允许有其他的构造方法使用 “@Autowire”;但是允许有多个构造方法同时使用 “@Autowired(required = false)”。

之后就是根据候选的构造方法实例化了。

protected BeanWrapper autowireConstructor(
    	String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] ctors, @Nullable Object[] explicitArgs) {

    return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
}

构造一个解析器来解析构造方法

public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
		@Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {

    // bean实例包装类
    BeanWrapperImpl bw = new BeanWrapperImpl();
    this.beanFactory.initBeanWrapper(bw);

    // 用于实例化的构造方法
    Constructor<?> constructorToUse = null;
    // 用于实例化的构造方法参数
    ArgumentsHolder argsHolderToUse = null;
    // 构造方法参数
    Object[] argsToUse = null;

    if (explicitArgs != null) {
        argsToUse = explicitArgs;
    }
    else {
        // 从缓存中尝试获取已经解析的构造方法
        
        // 保存待解析的参数
        Object[] argsToResolve = null;
        synchronized (mbd.constructorArgumentLock) {
            // 获取缓存中已解析的构造方法或工厂方法
            constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
            // 如果constructorToUse不为空 && mbd标记了构造方法参数已解析
            if (constructorToUse != null && mbd.constructorArgumentsResolved) {
                // 获取缓存中已解析的构造方法参数
                argsToUse = mbd.resolvedConstructorArguments;
                
                // 如果resolvedConstructorArguments为空,则从缓存中获取准备用于解析的构造函数参数,
                // constructorArgumentsResolved为true时,resolvedConstructorArguments和
                // preparedConstructorArguments必然有一个缓存了构造函数的参数
                if (argsToUse == null) {
                    argsToResolve = mbd.preparedConstructorArguments;
                }
            }
        }
        // 对参数进行解析
        if (argsToResolve != null) {
            argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve, true);
        }
    }

    // 如果要实例化的构造方法(即缓存中还不存在)和参数有一个为空,就得去解析
    if (constructorToUse == null || argsToUse == null) {
        // Take specified constructors, if any.
        Constructor<?>[] candidates = chosenCtors;
        if (candidates == null) {
            Class<?> beanClass = mbd.getBeanClass();
            try {
                // 如果入参chosenCtors为空,则获取beanClass的构造函数,
                // (mbd是否允许访问非公共构造函数和方法 ? 所有声明的构造函数:公共构造函数)
                candidates = (mbd.isNonPublicAccessAllowed() ?
                              beanClass.getDeclaredConstructors() : beanClass.getConstructors());
            }
            catch (Throwable ex) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                                "Resolution of declared constructors on bean Class [" + beanClass.getName() +
                                                "] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
            }
        }

        // 如果候选构造方法只有一个 && explicitArgs为空 && mbd没有缓存参数值
        if (candidates.length == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
            Constructor<?> uniqueCandidate = candidates[0];
            // 如果这唯一的候选构造方法没有参数,则使用该无参构造方法实例化,
            // 包装进BeanWrapperImpl后返回
            if (uniqueCandidate.getParameterCount() == 0) {
                synchronized (mbd.constructorArgumentLock) {
                    // 设置缓存
                    mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
                    mbd.constructorArgumentsResolved = true;
                    mbd.resolvedConstructorArguments = EMPTY_ARGS;
                }
                bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS));
                return bw;
            }
        }

        // 需要去解析构造方法
        
        // 判断是否要自动注入,传入的chosenCtors不为空(说明有构造方法是用@Autowired标注的)
        // || bean的注入模式是AUTOWIRE_CONSTRUCTOR
        boolean autowiring = (chosenCtors != null ||
                              mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
        ConstructorArgumentValues resolvedValues = null;

        // 构造方法参数个数
        int minNrOfArgs;
        if (explicitArgs != null) {
            minNrOfArgs = explicitArgs.length;
        }
        else {
            ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
            resolvedValues = new ConstructorArgumentValues();
            // 将此 bean 的构造函数参数解析为 resolvedValues 对象,
            // 这里主要是用于xml方式定义的
            minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
        }

        AutowireUtils.sortConstructors(candidates);
        int minTypeDiffWeight = Integer.MAX_VALUE;
        Set<Constructor<?>> ambiguousConstructors = null;
        LinkedList<UnsatisfiedDependencyException> causes = null;

        for (Constructor<?> candidate : candidates) {
            Class<?>[] paramTypes = candidate.getParameterTypes();

            if (constructorToUse != null && argsToUse != null && argsToUse.length > paramTypes.length) {
                // Already found greedy constructor that can be satisfied ->
                // do not look any further, there are only less greedy constructors left.
                break;
            }
            if (paramTypes.length < minNrOfArgs) {
                continue;
            }

            ArgumentsHolder argsHolder;
            if (resolvedValues != null) {
                try {
                    String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
                    if (paramNames == null) {
                        ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
                        if (pnd != null) {
                            paramNames = pnd.getParameterNames(candidate);
                        }
                    }
                    // 这个会去获取依赖,如果不存在则会先去实例化依赖
                    argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
                                                     getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1);
                }
                catch (UnsatisfiedDependencyException ex) {
                    if (logger.isTraceEnabled()) {
                        logger.trace("Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
                    }
                    // Swallow and try next constructor.
                    if (causes == null) {
                        causes = new LinkedList<>();
                    }
                    causes.add(ex);
                    continue;
                }
            }
            else {
                // Explicit arguments given -> arguments length must match exactly.
                if (paramTypes.length != explicitArgs.length) {
                    continue;
                }
                argsHolder = new ArgumentsHolder(explicitArgs);
            }

            int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
                                  argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
            // Choose this constructor if it represents the closest match.
            if (typeDiffWeight < minTypeDiffWeight) {
                constructorToUse = candidate;
                argsHolderToUse = argsHolder;
                argsToUse = argsHolder.arguments;
                minTypeDiffWeight = typeDiffWeight;
                ambiguousConstructors = null;
            }
            else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
                if (ambiguousConstructors == null) {
                    ambiguousConstructors = new LinkedHashSet<>();
                    ambiguousConstructors.add(constructorToUse);
                }
                ambiguousConstructors.add(candidate);
            }
        }

        if (constructorToUse == null) {
            if (causes != null) {
                UnsatisfiedDependencyException ex = causes.removeLast();
                for (Exception cause : causes) {
                    this.beanFactory.onSuppressedException(cause);
                }
                throw ex;
            }
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                            "Could not resolve matching constructor " +
                                            "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
        }
        else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                            "Ambiguous constructor matches found in bean '" + beanName + "' " +
                                            "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
                                            ambiguousConstructors);
        }

        if (explicitArgs == null && argsHolderToUse != null) {
            argsHolderToUse.storeCache(mbd, constructorToUse);
        }
    }

    Assert.state(argsToUse != null, "Unresolved constructor arguments");
    bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
    return bw;
}

这里就看最简单的使用无参构造方法实例化。

protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
    try {
        Object beanInstance;
        final BeanFactory parent = this;
        if (System.getSecurityManager() != null) {
            beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
                                                         getInstantiationStrategy().instantiate(mbd, beanName, parent),
                                                         getAccessControlContext());
        }
        else {
            // 实例化bean
            beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
        }
        // 将bean用BeanWrapper类包装
        BeanWrapper bw = new BeanWrapperImpl(beanInstance);
        initBeanWrapper(bw);
        return bw;
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
    }
}

使用策略类SimpleInstantiationStrategy实例化

public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
    // Don't override the class with CGLIB if no overrides.
    if (!bd.hasMethodOverrides()) {
        Constructor<?> constructorToUse;
        synchronized (bd.constructorArgumentLock) {
            constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
            if (constructorToUse == null) {
                final Class<?> clazz = bd.getBeanClass();
                if (clazz.isInterface()) {
                    throw new BeanInstantiationException(clazz, "Specified class is an interface");
                }
                try {
                    if (System.getSecurityManager() != null) {
                        constructorToUse = AccessController.doPrivileged(
                            (PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
                    }
                    else {
                        // 通过反射得到构造方法
                        constructorToUse = clazz.getDeclaredConstructor();
                    }
                    // 将构造方法赋给bean定义的resolvedConstructorOrFactoryMethod
                    // 如果是多例,那下次就无需再次解析,就可以直接创建bean
                    bd.resolvedConstructorOrFactoryMethod = constructorToUse;
                }
                catch (Throwable ex) {
                    throw new BeanInstantiationException(clazz, "No default constructor found", ex);
                }
            }
        }
        // 使用bean工具类根据构造方法实例化
        return BeanUtils.instantiateClass(constructorToUse);
    }
    else {
        // Must generate CGLIB subclass.
        // 
        return instantiateWithMethodInjection(bd, beanName, owner);
    }
}

最后使用bean工具类根据构造方法实例化

public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
    Assert.notNull(ctor, "Constructor must not be null");
    try {
        // 如果构造方法是私有的,则先设置成公开的可访问的
        ReflectionUtils.makeAccessible(ctor);
        // 这里支持带有可选参数和默认值的 Kotlin 类,
        // 通常就使用ctor.newInstance(args)就行了
        return (KotlinDetector.isKotlinReflectPresent() && KotlinDetector.isKotlinType(ctor.getDeclaringClass()) ?
                KotlinDelegate.instantiateClass(ctor, args) : ctor.newInstance(args));
    }
    catch (InstantiationException ex) {
        throw new BeanInstantiationException(ctor, "Is it an abstract class?", ex);
    }
    catch (IllegalAccessException ex) {
        throw new BeanInstantiationException(ctor, "Is the constructor accessible?", ex);
    }
    catch (IllegalArgumentException ex) {
        throw new BeanInstantiationException(ctor, "Illegal arguments for constructor", ex);
    }
    catch (InvocationTargetException ex) {
        throw new BeanInstantiationException(ctor, "Constructor threw exception", ex.getTargetException());
    }
}

最终是通过newInstance来实例化对象。

2、应用后置处理器MergedBeanDefinitionPostProcessor

允许修改MergedBeanDefinition,@Autowired注解正是通过此方法实现注入类型的预解析

protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
        if (bp instanceof MergedBeanDefinitionPostProcessor) {
            MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
            bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
        }
    }
}

遍历所有的bean后置处理器,找到其中MergedBeanDefinitionPostProcessor类型的处理器调用postProcessMergedBeanDefinition方法。
这里需要说下AutowiredAnnotationBeanPostProcessor这个类,它的postProcessMergedBeanDefinition方法会对要注入的属性进行预解析

@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
    // // 找到需要注入的属性元数据
    InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
    metadata.checkConfigMembers(beanDefinition);
}

private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
    // Fall back to class name as cache key, for backwards compatibility with custom callers.
    // 先从缓存中查找下
    String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
    // Quick check on the concurrent map first, with minimal locking.
    // 判断是否需要重新解析,如果metadata是空的或者metadata里目标类跟clazz不一样就重新解析
	// 这里使用双重检查锁方式保证线程安全
    InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
    if (InjectionMetadata.needsRefresh(metadata, clazz)) {
        synchronized (this.injectionMetadataCache) {
            metadata = this.injectionMetadataCache.get(cacheKey);
            if (InjectionMetadata.needsRefresh(metadata, clazz)) {
                if (metadata != null) {
                    metadata.clear(pvs);
                }
                // 构建需要注入的属性的元数据,然后放入缓存
                metadata = buildAutowiringMetadata(clazz);
                // 将metadata放入缓存,这样在后面进行属性注入时就无需再次解析了
                this.injectionMetadataCache.put(cacheKey, metadata);
            }
        }
    }
    return metadata;
}

private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
    List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
    Class<?> targetClass = clazz;

    // 构建InjectedElement 对象实际也就是遍历bean的所有字段和相关方法,
    // 过滤带有@Autowired和@Value 注解属性的构造成InjectedElement 对象
    do {
        final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();

        ReflectionUtils.doWithLocalFields(targetClass, field -> {
            AnnotationAttributes ann = findAutowiredAnnotation(field);
            if (ann != null) {
                if (Modifier.isStatic(field.getModifiers())) {
                    if (logger.isInfoEnabled()) {
                        logger.info("Autowired annotation is not supported on static fields: " + field);
                    }
                    return;
                }
                boolean required = determineRequiredStatus(ann);
                currElements.add(new AutowiredFieldElement(field, required));
            }
        });

        ReflectionUtils.doWithLocalMethods(targetClass, method -> {
            Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
            if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
                return;
            }
            AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
            if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
                if (Modifier.isStatic(method.getModifiers())) {
                    if (logger.isInfoEnabled()) {
                        logger.info("Autowired annotation is not supported on static methods: " + method);
                    }
                    return;
                }
                if (method.getParameterCount() == 0) {
                    if (logger.isInfoEnabled()) {
                        logger.info("Autowired annotation should only be used on methods with parameters: " +
                                    method);
                    }
                }
                boolean required = determineRequiredStatus(ann);
                PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
                currElements.add(new AutowiredMethodElement(method, required, pd));
            }
        });

        elements.addAll(0, currElements);
        targetClass = targetClass.getSuperclass();
    }
    while (targetClass != null && targetClass != Object.class);

    return new InjectionMetadata(clazz, elements);
}

3、判断是否要提前暴露该bean

必须满足 单例 && 允许循环依赖 && 该bean正在创建

4、提前暴露该bean的ObjectFactory

该目的是为了解决循环依赖

addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

看下addSingletonFactory方法

protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
    Assert.notNull(singletonFactory, "Singleton factory must not be null");
    synchronized (this.singletonObjects) {
        // 如果单例缓存中还不存在该bean,则将该bean的ObjectFactory放入单例工厂中
        if (!this.singletonObjects.containsKey(beanName)) {
            this.singletonFactories.put(beanName, singletonFactory);
            this.earlySingletonObjects.remove(beanName);
            this.registeredSingletons.add(beanName);
        }
    }
}

如果单例缓存中还不存在该bean,则将该bean的ObjectFactory放入单例工厂中。
getEarlyBeanReference方法是通过调用SmartInstantiationAwareBeanPostProcessor的getEarlyBeanReference方法来得到提早暴露的bean

protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
    Object exposedObject = bean;
    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
                SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
                exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
            }
        }
    }
    return exposedObject;
}

如果没有aop或自定义的SmartInstantiationAwareBeanPostProcessor,则默认的几个处理器是直接返回bean的,没有对bean进行操作。

5、进行属性填充

这步会进行属性填充,自动注入也是在这步完成的。如果所依赖的属性是其它的bean,则会进行其它bean的初始化。
放在下一篇Spring IOC 源码解析之populateBean(五)进行解析。

6、处理 bean 初始化完成后的各种回调,比如后置处理,init方法等

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            invokeAwareMethods(beanName, bean);
            return null;
        }, getAccessControlContext());
    }
    else {
        // 6.1、调用Aware接口方法
        invokeAwareMethods(beanName, bean);
    }

    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        // 6.2、调用bean后置处理器的postProcessBeforeInitialization方法
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }

    try {
        // 6.3、初始化bean,调用init方法
        invokeInitMethods(beanName, wrappedBean, mbd);
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
            (mbd != null ? mbd.getResourceDescription() : null),
            beanName, "Invocation of init method failed", ex);
    }
    if (mbd == null || !mbd.isSynthetic()) {
        // 6.4、调用bean后置处理器的postProcessAfterInitialization方法
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }

    return wrappedBean;
}

6.1、首先会调用Aware接口方法

private void invokeAwareMethods(final String beanName, final Object bean) {
    if (bean instanceof Aware) {
        if (bean instanceof BeanNameAware) {
            ((BeanNameAware) bean).setBeanName(beanName);
        }
        if (bean instanceof BeanClassLoaderAware) {
            ClassLoader bcl = getBeanClassLoader();
            if (bcl != null) {
                ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
            }
        }
        if (bean instanceof BeanFactoryAware) {
            ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
        }
    }
}

会判断bean是否是Aware接口的实现类,然后再判断是否是BeanNameAware,BeanClassLoaderAware和BeanFactoryAware接口的实现类,分别调用各自的方法设置属性。
6.2、调用bean后置处理器的postProcessBeforeInitialization方法

@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
    throws BeansException {

    Object result = existingBean;
    for (BeanPostProcessor processor : getBeanPostProcessors()) {
        Object current = processor.postProcessBeforeInitialization(result, beanName);
        if (current == null) {
            return result;
        }
        result = current;
    }
    return result;
}

获取到所哟的bean后置处理器,然后分别调用postProcessBeforeInitialization方法对bean做初始化前的后置处理,如果有一个方法返回了null,则会直接结束循环,返回上一次调用后的结果。
这里有一个比较重要的后置处理器ApplicationContextAwareProcessor,也是专门用来判断是否实现了各个Aware接口。
6.3、初始化bean,调用init方法

protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
    	throws Throwable {

    // 判断是否实现了InitializingBean接口,如果是则调用afterPropertiesSet方法
    boolean isInitializingBean = (bean instanceof InitializingBean);
    if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
        if (logger.isTraceEnabled()) {
            logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
        }
        if (System.getSecurityManager() != null) {
            try {
                AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
                    ((InitializingBean) bean).afterPropertiesSet();
                    return null;
                }, getAccessControlContext());
            }
            catch (PrivilegedActionException pae) {
                throw pae.getException();
            }
        }
        else {
            // 调用afterPropertiesSet
            ((InitializingBean) bean).afterPropertiesSet();
        }
    }

    // 上面是调用实现InitializingBean接口的初始化方法,
    // 现在是调用自定义的初始化方法
    if (mbd != null && bean.getClass() != NullBean.class) {
        String initMethodName = mbd.getInitMethodName();
        // 如果实现了InitializingBean接口并且也自定义了初始化方法,
        // 则在上面执行完afterPropertiesSet后会执行这里的自定义初始化方法,
        // 但如果自定义方法名也是叫afterPropertiesSet,则这里不会再执行
        if (StringUtils.hasLength(initMethodName) &&
            !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
            !mbd.isExternallyManagedInitMethod(initMethodName)) {
            // 调用自定义的初始化方法
            invokeCustomInitMethod(beanName, bean, mbd);
        }
    }
}
protected void invokeCustomInitMethod(String beanName, final Object bean, RootBeanDefinition mbd)
    	throws Throwable {

    // 初始化方法名
    String initMethodName = mbd.getInitMethodName();
    Assert.state(initMethodName != null, "No init method set");
    // 获取到方法对象
    Method initMethod = (mbd.isNonPublicAccessAllowed() ?
                         BeanUtils.findMethod(bean.getClass(), initMethodName) :
                         ClassUtils.getMethodIfAvailable(bean.getClass(), initMethodName));

    if (initMethod == null) {
        // 如果初始化方法是空的但又却要强制执行初始化方法,则抛异常
        if (mbd.isEnforceInitMethod()) {
            throw new BeanDefinitionValidationException("Could not find an init method named '" +
                                                        initMethodName + "' on bean with name '" + beanName + "'");
        }
        else {
            if (logger.isTraceEnabled()) {
                logger.trace("No default init method named '" + initMethodName +
                             "' found on bean with name '" + beanName + "'");
            }
            // Ignore non-existent default lifecycle methods.
            return;
        }
    }

    if (logger.isTraceEnabled()) {
        logger.trace("Invoking init method  '" + initMethodName + "' on bean with name '" + beanName + "'");
    }
    // 获得原接口的方法对象,如果没有则用当前的
    Method methodToInvoke = ClassUtils.getInterfaceMethodIfPossible(initMethod);

    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            ReflectionUtils.makeAccessible(methodToInvoke);
            return null;
        });
        try {
            AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () ->
                                          methodToInvoke.invoke(bean), getAccessControlContext());
        }
        catch (PrivilegedActionException pae) {
            InvocationTargetException ex = (InvocationTargetException) pae.getException();
            throw ex.getTargetException();
        }
    }
    else {
        try {
            // 使用反射方式调用初始化方法
            ReflectionUtils.makeAccessible(methodToInvoke);
            methodToInvoke.invoke(bean);
        }
        catch (InvocationTargetException ex) {
            throw ex.getTargetException();
        }
    }
}

调到自定义初始化方法有以下两种方式:
①使用xml方式时在bean中设置了init-method属性,如下:

<bean id="student" class="com.huang.sourcelearn.Student" init-method="init"/>

②使用@Bean注解时指定初始化方法,如下

@Configuration
@ComponentScan("com.huang.sourcelearn")
public class Config {

    @Bean(initMethod = "init")
    public Student student() {
        return new Student();
    }
}

这两种方式都会调到上面讲到自定义初始化逻辑。
6.4、调用bean后置处理器的postProcessAfterInitialization方法

@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
    throws BeansException {

    Object result = existingBean;
    for (BeanPostProcessor processor : getBeanPostProcessors()) {
        Object current = processor.postProcessAfterInitialization(result, beanName);
        if (current == null) {
            return result;
        }
        result = current;
    }
    return result;
}

也是获取到所有的bean后置处理器,然后依次调用postProcessAfterInitialization方法,对bean做初始化后的后置处理。

7、如果允许提前曝光实例,则进行循环依赖检查

if (earlySingletonExposure) {
    // earlySingletonReference只有在当前解析的bean存在循环依赖的情况下才会不为空
    // false表示只会从一级和二级缓存中查找,如果没有循环依赖,当前bean还在三级缓存中,
    // 一二级缓存还没有该bean(如果没有循环依赖和代理的情况下,bean不会在二级缓存存在过)
    Object earlySingletonReference = getSingleton(beanName, false);
    // todo 这部分有点看不懂
    if (earlySingletonReference != null) {
        if (exposedObject == bean) {
            exposedObject = earlySingletonReference;
        }
        else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
            String[] dependentBeans = getDependentBeans(beanName);
            Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
            for (String dependentBean : dependentBeans) {
                if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                    actualDependentBeans.add(dependentBean);
                }
            }
            if (!actualDependentBeans.isEmpty()) {
                throw new BeanCurrentlyInCreationException(beanName,
                                                           "Bean with name '" + beanName + "' has been injected into other beans [" +
                                                           StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                                                           "] in its raw version as part of a circular reference, but has eventually been " +
                                                           "wrapped. This means that said other beans do not use the final version of the " +
                                                           "bean. This is often the result of over-eager type matching - consider using " +
                                                           "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
            }
        }
    }
}

这部分得配合下面这张图可能会清晰点,AB循环依赖的情况下,A走到这步时earlySingletonReference才不是空的,因为在B获取A时将A从三级缓存放到了二级缓存。
在这里插入图片描述

8、注册用于销毁的bean

执行销毁操作的有三种:自定义destroy方法、DisposableBean接口、DestructionAwareBeanPostProcessor。这个方法就不再解析了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值