spring核心第4 章:BeanFactory

作用

提供getBean方法。可以获取所有spring的bean对象。

整体实现功能为 通过BeanDefinitionRegistry提供bean定义。并且通过BeanDefinition创建、初始化、解决依赖注入bean对象。将单例对象保存在SingletonBeanRegistry中。

主要子类

接口的主要实现是DefaultListableBeanFactory

继承关系

在这里插入图片描述

BeanFactory

定义了各种getBean 的方法

ListableBeanFactory

可列举的BeanFactory 定义了批量获取bean的方法。比如可以一次获取全部的bean(太暴力了),根据类型获取bean.

HierarchicalBeanFactory

定义父BeanFactory

ConfigurableBeanFactory

可配置的BeanFactory。其中可配置的内容有:

BeanExpressionResolver
ConversionService
PropertyEditorRegistrar
TypeConverter
StringValueResolver
BeanPostProcessor

AutowireCapableBeanFactory

可以自动注入的BeanFactory。定义了与自动装配相关的接口

FactoryBeanRegistrySupport

是FactoryBeanRegistrySupport的扩展
其中添加成员变量

	private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<>(16);

将所有通过FactoryBean的get方法获取到的单例对象保存在这里,提供使用

AbstractBeanFactory

BeanFactory的抽象实现,其中主要实现的有ConfigurableBeanFactory的所有方法,和部分getBean方法。
下面主要讲解getBean的方法

getBean
	@Override
	public Object getBean(String name) throws BeansException {
		return doGetBean(name, null, null, false);
	}

	@Override
	public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
		return doGetBean(name, requiredType, null, false);
	}

	@Override
	public Object getBean(String name, Object... args) throws BeansException {
		return doGetBean(name, null, args, false);
	}


我们可以看到所有的getBean方法最终都调用了doGetBean方法

doGetBean
protected <T> T doGetBean(
			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException {
        //去除 & ,转换别名
		String beanName = transformedBeanName(name);
		Object bean;

		// 尝试从单例中获取对象
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			if (logger.isTraceEnabled()) {
				if (isSingletonCurrentlyInCreation(beanName)) {
					logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				}
				else {
					logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
			//可以获取到对象是调用getObjectForBeanInstance,解决FactoryBean相关问题
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		else {
			// 判断当前bean是否正在创建。
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			// 尝试从父容器中获取
			BeanFactory parentBeanFactory = getParentBeanFactory();
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// Not found -> check parent.
				String nameToLookup = originalBeanName(name);
				if (parentBeanFactory instanceof AbstractBeanFactory) {
					return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
							nameToLookup, requiredType, args, typeCheckOnly);
				}
				else if (args != null) {
					// Delegation to parent with explicit args.
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else if (requiredType != null) {
					// No args -> delegate to standard getBean method.
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
				else {
					return (T) parentBeanFactory.getBean(nameToLookup);
				}
			}

			if (!typeCheckOnly) {
				markBeanAsCreated(beanName);
			}


            //到这一步说明,当前bean还没有被创建。这个时候就需要获取BeanDefinition,并创建bean
			StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
					.tag("beanName", name);
			try {
				if (requiredType != null) {
					beanCreation.tag("beanType", requiredType::toString);
				}
				//融合bean定义。这一步是将父定义与当前定义进行融合
				RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);

				// 获取依赖,优先初始化依赖。可以通过@DependsOn来定义依赖
				String[] dependsOn = mbd.getDependsOn();
				if (dependsOn != null) {
					for (String dep : dependsOn) {
						if (isDependent(beanName, dep)) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
						}
						//注册依赖,将bean的依赖关系保存在dependentBeanMap成员变量中
						registerDependentBean(dep, beanName);
						try {
						    //先初始化依赖
							getBean(dep);
						}
						catch (NoSuchBeanDefinitionException ex) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
						}
					}
				}

				// 如果是单例通过createBean 方法初始化bean,并通过getSingleton 注册。
				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, () -> {
						try {
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							// Explicitly remove instance from singleton cache: It might have been put there
							// eagerly by the creation process, to allow for circular reference resolution.
							// Also remove any beans that received a temporary reference to the bean.
							destroySingleton(beanName);
							throw ex;
						}
					});
				
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}
                //如果是多例,就只调用createBean
				else if (mbd.isPrototype()) {
					// It's a prototype -> create a new instance.
					Object prototypeInstance = null;
					try {
						beforePrototypeCreation(beanName);
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
						afterPrototypeCreation(beanName);
					}
					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}

				else {
					String scopeName = mbd.getScope();
					if (!StringUtils.hasLength(scopeName)) {
						throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
					}
					Scope scope = this.scopes.get(scopeName);
					if (scope == null) {
						throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
					}
					try {
					
					    //其他情况,将其保存在对应的Scope 中。
						Object scopedInstance = scope.get(beanName, () -> {
							beforePrototypeCreation(beanName);
							try {
								return createBean(beanName, mbd, args);
							}
							finally {
								afterPrototypeCreation(beanName);
							}
						});
						bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
					}
					catch (IllegalStateException ex) {
						throw new ScopeNotActiveException(beanName, scopeName, ex);
					}
				}
			}
			catch (BeansException ex) {
				beanCreation.tag("exception", ex.getClass().toString());
				beanCreation.tag("message", String.valueOf(ex.getMessage()));
				cleanupAfterBeanCreationFailure(beanName);
				throw ex;
			}
			finally {
				beanCreation.end();
			}
		}

		//如果有需要,尝试类型转换
		if (requiredType != null && !requiredType.isInstance(bean)) {
			try {
				T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
				if (convertedBean == null) {
					throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
				}
				return convertedBean;
			}
			catch (TypeMismatchException ex) {
				if (logger.isTraceEnabled()) {
					logger.trace("Failed to convert bean '" + name + "' to required type '" +
							ClassUtils.getQualifiedName(requiredType) + "'", ex);
				}
				throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
			}
		}
		return (T) bean;
	}


整体过程我们可以看到如下步骤:

 * 1、获取真实的bean 名称 :(1)去除 & ,转换别名
 * 2、调用 getSingleton 。尝试获取bean对象。 {@linkplain DefaultSingletonBeanRegistry#getSingleton(String)}
 * 2.1 可以获取到bean 时,调用getObjectForBeanInstance 解析见:{@linkplain AbstractBeanFactoryStu#getObjectForBeanInstance()}
 * 3、通过 {@linkplain AbstractBeanFactory#isPrototypeCurrentlyInCreation(String)} 判断bean 是否真正创建。应该是构造函数的循环依赖判断
 * 4、去父beanFacory尝试获取,详细不解析了
 * 5、合并bean的父定义。生成新的完整bean定义。
 * 6、优先初始化依赖bean //@DependsOn 与 xml中的depends-on 属性。
 * 7、对于不同范围的做不同的处理,
 * 7.1、单例:如果是单例通过createBean 方法初始化bean,并通过getSingleton 注册。
 * 7.2、多例:如果是多例,就只调用createBean。
 * 8、如果有需要,尝试类型转换。使用 TypeConverter 对象

总结来说:

doGetBean完成了所以关于bean 获取的内容。当无法获取到bean是,调用createBean。将bean的创建过程留给子类实现。
getObjectForBeanInstance
在dogetBean方法中,在获取到bean对象后,都调用此方法,判断是获取BeanFactory对象本身,还是BeanFactory的get对象。
     * 1、判断是否以 & 开头。如果是 FactoryBean 子类,直接返回,也就是 &取出来的是bean工厂
     * 2、如果不是以 & 开头,不是 FactoryBean 子类,直接返回。
     * 3、调用{@linkplain FactoryBeanRegistrySupport#getCachedObjectForFactoryBean(String)} 获取缓存的 真实bean
     * 获取不到时{@linkplain FactoryBeanRegistrySupport#getObjectFromFactoryBean(FactoryBean, String, boolean)}调用getBean获取真实bean。

AbstractAutowireCapableBeanFactory

该类除了实现了AbstractBeanFactory 的createBean方法外,还实现了AutowireCapableBeanFactory的相关方法。

createBean

//去掉不重要的代码。可以看到在创建对象前,调用了resolveBeforeInstantiation 方法,若有bean返回,则直接使用返回的bean,否则继续调用doCreateBean 方法创建对象。
@Override
	protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			if (bean != null) {
				return bean;
			}
	
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
		
			return beanInstance;
		
	}

resolveBeforeInstantiation


	@Nullable
	protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
		Object bean = null;
		if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
			// Make sure bean class is actually resolved at this point.
			if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
				Class<?> targetType = determineTargetType(beanName, mbd);
				if (targetType != null) {
				
				    //迭代调用InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法,若返回不未null,则直接使用返回的对象
					bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
					if (bean != null) {
						bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
					}
				}
			}
			mbd.beforeInstantiationResolved = (bean != null);
		}
		return bean;
	}

doCreateBean

在createBean方法中,对象的创建是委托给本方法来实现的,具体代码如下:

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

		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		
		//创建bean对象
		if (instanceWrapper == null) {
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		Object bean = instanceWrapper.getWrappedInstance();
		Class<?> beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) {
			mbd.resolvedTargetType = beanType;
		}

		// 对应merged bean 执行 postProcessMergedBeanDefinition 方法
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				try {
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				mbd.postProcessed = true;
			}
		}

		// 将新new出来的对象,以ObejctFactory形式保存在singletonFactory中
		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");
			}
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
	 	    //填充属性
			populateBean(beanName, mbd, instanceWrapper);
			//执行初始化方法
			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);
			}
		}

		if (earlySingletonExposure) {
			Object earlySingletonReference = getSingleton(beanName, false);
			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 " +
								"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
					}
				}
			}
		}

		// Register bean as disposable.
		try {
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
		}

		return exposedObject;
	}


对于上面代码我们可以看到一下步骤:

1、通过createBeanInstance(beanName, mbd, args); 创建出来对象。
2、将新new出来的对象,以ObejctFactory形式保存在singletonFactory中。这里以ObejctFactory对象是因为如果对象被提取取出将会执行对应的后置处理器。
3、填充属性
4、执行初始化方法


接下来我们将具体分析这几步的具体内容。
createBeanInstance

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
		// Make sure bean class is actually resolved at this point.
		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 来创建对象
		Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
		if (instanceSupplier != null) {
			return obtainFromSupplier(instanceSupplier, beanName);
		}
        //对于有MethodName 使用 Method方法创建对象,在使用中就是我们用的@Bean注解
		if (mbd.getFactoryMethodName() != null) {
			return instantiateUsingFactoryMethod(beanName, mbd, args);
		}

		//接下来都是对于应该使用那种个构造函数的判断。
		boolean resolved = false;
		boolean autowireNecessary = false;
		if (args == null) {
			synchronized (mbd.constructorArgumentLock) {
				if (mbd.resolvedConstructorOrFactoryMethod != null) {
					resolved = true;
					autowireNecessary = mbd.constructorArgumentsResolved;
				}
			}
		}
		
		//有缓存的情况
		if (resolved) {
			if (autowireNecessary) {
				return autowireConstructor(beanName, mbd, null, null);
			}
			else {
				return instantiateBean(beanName, mbd);
			}
		}

		// 调用后置处理器确定使用哪个构造函数
		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
		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) {
			return autowireConstructor(beanName, mbd, ctors, null);
		}

		// No special handling: simply use no-arg constructor.
		return instantiateBean(beanName, mbd);
	}

通过上面代码我们可以看到对于创建bean一共进行了以下的步骤:

1、尝试使用instanceSupplier 创建对象
2、尝试使用MethodName 创建对象
3、不是上述方法创建对象是,使用反射的方法创建对象。
3.1、通过benaProcessor判断使用哪个构造函数来创建。
3.2、对于无指定构造函数时调用autowireConstructor
3.3、其他情况调用instantiateBean

下面对于这几步我们相信介绍。

MethodName 方式创建

在我们平常使用的 @Bean 注解就是使用的这种方式创建对象,下面是一个测试用例:


@Component
public class BeanParser {

    @Bean
    public BeanOnBeanTest beanOnBeanTest(){
        return new BeanOnBeanTest();
    }



    public static class  BeanOnBeanTest{

    }
}

在这里插入图片描述

我们可以看到通过@Bean 方法。当前bean的factoryMethodName方法就是我们指定的beanOnBeanTest。我们跟进源码查看


protected BeanWrapper instantiateUsingFactoryMethod(
			String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {

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

这里直接调用的是ConstructorResolver 方法。具体我们在起对应章节说明。

构造函数的选择 determineConstructorsFromBeanPostProcessors

前面章节我们通过调用determineConstructorsFromBeanPostProcessors 方法确定构造函数。代码如下:


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

		if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
		   //遍历所有的SmartInstantiationAwareBeanPostProcessor类型的BeanPostProcessor,如果返回值不为空则返回内容,如果为空则返回null。
			for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
				Constructor<?>[] ctors = bp.determineCandidateConstructors(beanClass, beanName);
				if (ctors != null) {
					return ctors;
				}
			}
		}
		return null;
	}

我们可以看到spring通过后置处理器来确定是否有指定的构造函数。而在默认的后置处理器中具体干了以下事情:

AutowiredAnnotationBeanPostProcessor 类
1、筛选出构造函数中包含Autowired和Value 注解
2、对于没有无参的构造函数时,选择出合适的构造函数

具体关于AutowiredAnnotationBeanPostProcessor 内容的解析可以看对应章节内容

autowireConstructor

当通过上一章节,我们指定了构造函数时,调用当前方法创建对象,代码如下:


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

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


我们可以看到直接调用了ConstructorResolver 方法来创建对象,其代码在对应章节说明

instantiateBean 午参的构造函数

当我们需要使用无参的构造函数时,调用当前方法。


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

在这里我们看到首先spring通过InstantiationStrategy 创建出对象,并且将其封装导BeanWrapper中。其中InstantiationStrategy默认使用的是CglibSubclassingInstantiationStrategy,对于这一点不再详细解析。

到目前这一步,我们解析完成了对象create的过程。解析来解析剩余过程

getEarlyBeanReference

在doCreateBean代码中。create完对象后后被封装为ObjectFactory对象保存起来

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

其中addSingletonFactory 方法我们在DefaultSingletonBeanRegistry类中进行了说明。而getEarlyBeanReference又做了什么事情,代码如下:

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


当当前的bean还没有初始化完成,但就被其他bean依赖时,我们就需要通过singletonFactory.getObject() 提前返回当前对象。而此时,我们其实需要的不是这个对象本身而是它的代理,这个时候就需要通过后置处理器的getEarlyBeanReference方法返回它的代理了。这一点在aop中可以体现。

populateBean 填充属性

populateBean方法就是对bean的方法和自动的填充,具体代码如下:


protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
		if (bw == null) {
			if (mbd.hasPropertyValues()) {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
			}
			else {
				// Skip property population phase for null instance.
				return;
			}
		}

		// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
		// state of the bean before properties are set. This can be used, for example,
		// to support styles of field injection.
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
				if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
					return;
				}
			}
		}

		PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
        //判断属性注入的类型
		int resolvedAutowireMode = mbd.getResolvedAutowireMode();
		if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
			// Add property values based on autowire by name if applicable.
			if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
				autowireByName(beanName, mbd, bw, newPvs);
			}
			// Add property values based on autowire by type if applicable.
			if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
				autowireByType(beanName, mbd, bw, newPvs);
			}
			pvs = newPvs;
		}

		boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
		boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

		PropertyDescriptor[] filteredPds = null;
		//使用后置处理器获取需要注入的对象
		if (hasInstAwareBpps) {
			if (pvs == null) {
				pvs = mbd.getPropertyValues();
			}
			for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
				PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
				if (pvsToUse == null) {
					if (filteredPds == null) {
						filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
					}
					pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
					if (pvsToUse == null) {
						return;
					}
				}
				pvs = pvsToUse;
			}
		}
		if (needsDepCheck) {
			if (filteredPds == null) {
				filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
			}
			checkDependencies(beanName, mbd, filteredPds, pvs);
		}
		
        //注入属性
		if (pvs != null) {
			applyPropertyValues(beanName, mbd, bw, pvs);
		}
	}



上面的代码共分为3步:

1、判断当前bean的byName还是byType。在springboot中,这部分代码无效。不做解析。
2、通过后置处理器注入属性,其中包括Autowired和Value 注解。这一点我们将在后置处理器中说明。
3、将前面两部分的属性注入到bean中。(下面的章节)

这些就是关于属性注入的内容。下面将介绍初始化的内容

initializeBean 初始化

执行bean的初始化方法及其在初始化前后的后者处理器。具体如下:


	protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
		//如果是Aware子类,则注入对应的属性
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		//执行BeforeInitialization方法
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}
        //执行初始化方法,2种形式。1、BeforeInitialization的子类;2、指定了对应的初始化方法
		try {
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}
		//执行AfterInitialization方法
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}



到目前为止。我们解析完成了对象创建的过程。

DefaultListableBeanFactory

在这个类中,bean的创建其父类已经实现。在这里主要说明的有2个方法。

1、通过class类型getBean
2、AutowireCapableBeanFactory 的resolveDependency实现
getBean

根据class 获取bean


	@Override
	public <T> T getBean(Class<T> requiredType) throws BeansException {
		return getBean(requiredType, (Object[]) null);
	}

	@SuppressWarnings("unchecked")
	@Override
	public <T> T getBean(Class<T> requiredType, @Nullable Object... args) throws BeansException {
		Assert.notNull(requiredType, "Required type must not be null");
		Object resolved = resolveBean(ResolvableType.forRawClass(requiredType), args, false);
		if (resolved == null) {
			throw new NoSuchBeanDefinitionException(requiredType);
		}
		return (T) resolved;
	}

我们可以看到最终是将class转换未Resolvable对象调用resolveBean

resolveBean

	@Nullable
	private <T> T resolveBean(ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) {
	    //通过resolveNamedBean 方法获取
		NamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, args, nonUniqueAsNull);
		if (namedBean != null) {
			return namedBean.getBeanInstance();
		}
		//在父类中获取
		BeanFactory parent = getParentBeanFactory();
		if (parent instanceof DefaultListableBeanFactory) {
			return ((DefaultListableBeanFactory) parent).resolveBean(requiredType, args, nonUniqueAsNull);
		}
		//通过ObjectProvider 获取
		else if (parent != null) {
			ObjectProvider<T> parentProvider = parent.getBeanProvider(requiredType);
			if (args != null) {
				return parentProvider.getObject(args);
			}
			else {
				return (nonUniqueAsNull ? parentProvider.getIfUnique() : parentProvider.getIfAvailable());
			}
		}
		return null;
	}
	
	
	private <T> NamedBeanHolder<T> resolveNamedBean(
			ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) throws BeansException {

		Assert.notNull(requiredType, "Required type must not be null");
		String[] candidateNames = getBeanNamesForType(requiredType);
        //多于一个候选时,尝试使用AutowireCandidate确定唯一
		if (candidateNames.length > 1) {
			List<String> autowireCandidates = new ArrayList<>(candidateNames.length);
			for (String beanName : candidateNames) {
				if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {
					autowireCandidates.add(beanName);
				}
			}
			if (!autowireCandidates.isEmpty()) {
				candidateNames = StringUtils.toStringArray(autowireCandidates);
			}
		}
        //候选确定时,直接返回
		if (candidateNames.length == 1) {
			String beanName = candidateNames[0];
			return new NamedBeanHolder<>(beanName, (T) getBean(beanName, requiredType.toClass(), args));
		}
		
		else if (candidateNames.length > 1) {
			Map<String, Object> candidates = CollectionUtils.newLinkedHashMap(candidateNames.length);
			for (String beanName : candidateNames) {
				if (containsSingleton(beanName) && args == null) {
					Object beanInstance = getBean(beanName);
					candidates.put(beanName, (beanInstance instanceof NullBean ? null : beanInstance));
				}
				else {
					candidates.put(beanName, getType(beanName));
				}
			}
			
			//通过isPrimary来确定
			String candidateName = determinePrimaryCandidate(candidates, requiredType.toClass());
			if (candidateName == null) {
			    //通过优先度确认
				candidateName = determineHighestPriorityCandidate(candidates, requiredType.toClass());
			}
			if (candidateName != null) {
				Object beanInstance = candidates.get(candidateName);
				if (beanInstance == null || beanInstance instanceof Class) {
					beanInstance = getBean(candidateName, requiredType.toClass(), args);
				}
				return new NamedBeanHolder<>(candidateName, (T) beanInstance);
			}
			if (!nonUniqueAsNull) {
				throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet());
			}
		}

		return null;
	}

上面对于bean获取分为以下几步:

  1. 排除autowireCandidate 为false的对象。@Bean(autowireCandidate = false),参考:https://blog.csdn.net/likun557/article/details/104438417
  2. 候选对象唯一时,直接返回
  3. 选包含 @Primary 的bean优先注入。参考https://blog.csdn.net/likun557/article/details/104404333
  4. 判断优先级,返回优先级高的
resolveDependency
该方法主要是用于解决spring的依赖问题。比如:我们通过注解@Autowired或者@Value在自动和方法上的自动注入都是通过当前方法
示例
下面两个类分别是通过@Value和@Autowired注入相关内容:
@Component

public class HaveBeanPaulateBean {

    @Autowired
    @Qualifier("notPapulateBean")
    private NotPapulateBean notPapulateBean;


    public NotPapulateBean getNotPapulateBean() {
        return notPapulateBean;
    }

    public void setNotPapulateBean(NotPapulateBean notPapulateBean) {
        this.notPapulateBean = notPapulateBean;
    }
}


@Component
public class HaveValuePaulateBean {

    @Value("1")
    private int a;

    @Value("字符串测试")
    private String b;

    @Value("${spring.datasource.username}")
    private String c;


}


通过dubug我们可以看到下图内容:

在这里插入图片描述

在这里插入图片描述

源码说明

    /**
    * 参数说明:
    * descriptor 对于需要注入的 字段或者方法 统一的封装描述
    * requestingBeanName 被注入对象class的bean名称
    * autowiredBeanNames 注入目标的bean名称
    * typeConverter 数据类型转换器
    *
    */
    @Override
	@Nullable
	public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
        //为descriptor 设置 ParameterNameDiscoverer 对象
		descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
		//对于特殊类型的数据进行不同的处理。
		if (Optional.class == descriptor.getDependencyType()) {
			return createOptionalDependency(descriptor, requestingBeanName);
		}
		else if (ObjectFactory.class == descriptor.getDependencyType() ||
				ObjectProvider.class == descriptor.getDependencyType()) {
			return new DependencyObjectProvider(descriptor, requestingBeanName);
		}
		else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
			return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
		}
		else {
			Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
					descriptor, requestingBeanName);
			if (result == null) {
				result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
			}
			return result;
		}
	}

上面代码共分为以下几步:

1、为descriptor 设置 ParameterNameDiscoverer 对象
2、不同的数据类型分为不同情况处理
3、所有类型,最终都会调用到doResolveDependency方法中

我们继续跟进doResolveDependency方法



@Nullable
	public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

		InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
		try {
		
		    //通过resolveShortcut提取获取对象,一般是一个空实现,没有作用。
			Object shortcut = descriptor.resolveShortcut(this);
			if (shortcut != null) {
				return shortcut;
			}
            //获取目标的class
			Class<?> type = descriptor.getDependencyType();
			//通过AutowireCandidateResolver对象解决@Value注入情况
			Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
			if (value != null) {
			    //如果是字符串,通过StringValueResolver 解决 ${}占位符问题。
				if (value instanceof String) {
					String strVal = resolveEmbeddedValue((String) value);
					BeanDefinition bd = (beanName != null && containsBean(beanName) ?
							getMergedBeanDefinition(beanName) : null);
					value = evaluateBeanDefinitionString(strVal, bd);
				}
				//如果有需要通过TypeConverter 转换类型
				TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
				try {
					return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
				}
				catch (UnsupportedOperationException ex) {
					// A custom TypeConverter which does not support TypeDescriptor resolution...
					return (descriptor.getField() != null ?
							converter.convertIfNecessary(value, type, descriptor.getField()) :
							converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
				}
			}
            //处理集合情况。比如:数组、Collection、Map等类型
			Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
			if (multipleBeans != null) {
				return multipleBeans;
			}
            //通过findAutowireCandidates 获取到所有匹配的情况
			Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
			
			//如果是必须的情况,抛出异常,否则返回null
			if (matchingBeans.isEmpty()) {
				if (isRequired(descriptor)) {
					raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
				}
				return null;
			}

			String autowiredBeanName;
			Object instanceCandidate;

            //有多个匹配值时通过determineAutowireCandidate 方法确定唯一值。
			if (matchingBeans.size() > 1) {
				autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
				if (autowiredBeanName == null) {
					if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
						return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
					}
					else {
						// In case of an optional Collection/Map, silently ignore a non-unique case:
						// possibly it was meant to be an empty collection of multiple regular beans
						// (before 4.3 in particular when we didn't even look for collection beans).
						return null;
					}
				}
				instanceCandidate = matchingBeans.get(autowiredBeanName);
			}
			//只有一个时,返回确定的那个值。
			else {
				// We have exactly one match.
				Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
				autowiredBeanName = entry.getKey();
				instanceCandidate = entry.getValue();
			}

			if (autowiredBeanNames != null) {
				autowiredBeanNames.add(autowiredBeanName);
			}
			if (instanceCandidate instanceof Class) {
				instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
			}
			Object result = instanceCandidate;
			if (result instanceof NullBean) {
				if (isRequired(descriptor)) {
					raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
				}
				result = null;
			}
			if (!ClassUtils.isAssignableValue(type, result)) {
				throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
			}
			return result;
		}
		finally {
			ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
		}
	}

整体来说逻辑如下:

对于@Value注解:
    1、通过AutowireCandidateResolver对象解决@Value注入的值
    2、如果是字符串,通过StringValueResolver 解决 ${}占位符问题。
    3、如果有需要通过TypeConverter 转换类型
    
对于@AutoWired注解:
    1、调用 resolveMultipleBeans 方法处理集合情况包括:数组、Collection、Map等类型
    2、通过findAutowireCandidates 方法返回所有查询到的对象
    3、当只有几个结果的时候直接返回
    4、当有多个结果的时候通过determineAutowireCandidate 方法确定唯一

上面的内容中AutowireCandidateResolver、StringValueResolver 、TypeConverter 说明将在其具体的文档中解析,下面不做详细说明我们主要关注点在
resolveMultipleBeans、findAutowireCandidates、determineAutowireCandidate 方法中。

resolveMultipleBeans

处理对象为集合的情况比如:数组、Collection、Map等类型


@Nullable
	private Object resolveMultipleBeans(DependencyDescriptor descriptor, @Nullable String beanName,
			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) {

		Class<?> type = descriptor.getDependencyType();

		if (descriptor instanceof StreamDependencyDescriptor) {
			Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
			if (autowiredBeanNames != null) {
				autowiredBeanNames.addAll(matchingBeans.keySet());
			}
			Stream<Object> stream = matchingBeans.keySet().stream()
					.map(name -> descriptor.resolveCandidate(name, type, this))
					.filter(bean -> !(bean instanceof NullBean));
			if (((StreamDependencyDescriptor) descriptor).isOrdered()) {
				stream = stream.sorted(adaptOrderComparator(matchingBeans));
			}
			return stream;
		}
		else if (type.isArray()) {
			Class<?> componentType = type.getComponentType();
			ResolvableType resolvableType = descriptor.getResolvableType();
			Class<?> resolvedArrayType = resolvableType.resolve(type);
			if (resolvedArrayType != type) {
				componentType = resolvableType.getComponentType().resolve();
			}
			if (componentType == null) {
				return null;
			}
			Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType,
					new MultiElementDescriptor(descriptor));
			if (matchingBeans.isEmpty()) {
				return null;
			}
			if (autowiredBeanNames != null) {
				autowiredBeanNames.addAll(matchingBeans.keySet());
			}
			TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
			Object result = converter.convertIfNecessary(matchingBeans.values(), resolvedArrayType);
			if (result instanceof Object[]) {
				Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
				if (comparator != null) {
					Arrays.sort((Object[]) result, comparator);
				}
			}
			return result;
		}
		else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
			Class<?> elementType = descriptor.getResolvableType().asCollection().resolveGeneric();
			if (elementType == null) {
				return null;
			}
			Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType,
					new MultiElementDescriptor(descriptor));
			if (matchingBeans.isEmpty()) {
				return null;
			}
			if (autowiredBeanNames != null) {
				autowiredBeanNames.addAll(matchingBeans.keySet());
			}
			TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
			Object result = converter.convertIfNecessary(matchingBeans.values(), type);
			if (result instanceof List) {
				if (((List<?>) result).size() > 1) {
					Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
					if (comparator != null) {
						((List<?>) result).sort(comparator);
					}
				}
			}
			return result;
		}
		else if (Map.class == type) {
			ResolvableType mapType = descriptor.getResolvableType().asMap();
			Class<?> keyType = mapType.resolveGeneric(0);
			if (String.class != keyType) {
				return null;
			}
			Class<?> valueType = mapType.resolveGeneric(1);
			if (valueType == null) {
				return null;
			}
			Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType,
					new MultiElementDescriptor(descriptor));
			if (matchingBeans.isEmpty()) {
				return null;
			}
			if (autowiredBeanNames != null) {
				autowiredBeanNames.addAll(matchingBeans.keySet());
			}
			return matchingBeans;
		}
		else {
			return null;
		}
	}

我们可以看到,通过不太情况的判断,最终都是通过findAutowireCandidates 获取bean对象,然后做的各自分装。

findAutowireCandidates

获取所有符合要求的依赖对象。


protected Map<String, Object> findAutowireCandidates(
			@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
        //通过类型获取所有依赖,最终调用的是getBeanNamesForType 方法上面章节有说明
		String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
				this, requiredType, true, descriptor.isEager());
		//结果的候选集
		Map<String, Object> result = CollectionUtils.newLinkedHashMap(candidateNames.length);
		
		//优先处理resolvableDependencies内的类型
		for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {
			Class<?> autowiringType = classObjectEntry.getKey();
			if (autowiringType.isAssignableFrom(requiredType)) {
				Object autowiringValue = classObjectEntry.getValue();
				autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
				if (requiredType.isInstance(autowiringValue)) {
					result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
					break;
				}
			}
		}
		//循环所有候选情况通过isAutowireCandidate判断是否符合要求,并通过addCandidateEntry 添加对象
		for (String candidate : candidateNames) {
			if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
				addCandidateEntry(result, candidate, descriptor, requiredType);
			}
		}
		if (result.isEmpty()) {
			boolean multiple = indicatesMultipleBeans(requiredType);
			// Consider fallback matches if the first pass failed to find anything...
			DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
			for (String candidate : candidateNames) {
				if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor) &&
						(!multiple || getAutowireCandidateResolver().hasQualifier(descriptor))) {
					addCandidateEntry(result, candidate, descriptor, requiredType);
				}
			}
			if (result.isEmpty() && !multiple) {
				// Consider self references as a final pass...
				// but in the case of a dependency collection, not the very same bean itself.
				for (String candidate : candidateNames) {
					if (isSelfReference(beanName, candidate) &&
							(!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
							isAutowireCandidate(candidate, fallbackDescriptor)) {
						addCandidateEntry(result, candidate, descriptor, requiredType);
					}
				}
			}
		}
		return result;
	}

到这一步我们可以看到:

  1. 首先通过类型获取所有依赖。
  2. 之后优先处理特殊类:resolvableDependencies集合的内容。
  3. 再通过isAutowireCandidate 方法当前类是否符合要求,其中@Qualifier注解就在这一步进行筛选。
  4. 最后通过addCandidateEntry 获取对象并添加到候选集中。

对于isAutowireCandidate 方法最终会调用:AutowireCandidateResolver的 isAutowireCandidate方法。我们在器进行解析

对于addCandidateEntry则是调用beanFactory.getBean(beanName) 不再详细解析

目前就剩下最后的 determineAutowireCandidate方法多个返回值时确定需要的内容。其实后调用 determinePrimaryCandidate 方法。我们在上面的解析中也做了说明。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值