Spring Bean的完整生命周期源码解析(从容器创建到Bean的销毁)

一、前言

Spring Bean的生命周期是Spring面试的高频热点问题,网上很多都是直接从Bean的实例化、初始化、使用、销毁四个方面介绍,本文将从源码的角度入手,详细介绍Bean的生命周,从容器的创建到Bean的销毁。

二、Bean的生命周期流程图

以下是我根据源码整理的完整的Bean的生命周期流程图,可以参考流程图阅读源码,基本每个步骤都有注释,用心去感受,跟着图例阅读,还是比较通俗易懂

三、源码分析 

1、spring容器启动,调用ApplicationContext容器,将XML文件或者配置类作为参数传入对应的容器,容器启动时,会帮我们配置文件路径。
2、之后调用register()方法,解析配置类,并将配置类封装成BeanDefinition对象注册到BeanDefinitionRegister(Bean定义注册中心)
3、之后调用refresh(),它的作用就是:在创建I0C容器前,如果已经有容器存在,则需要把已有的容器销毁和关闭,以保证在refresh之后使用的是新建立起来的IOC容器。refresh的作用类似于对1OC容器的重启,对容器进行初始化,包括Bean的生命周期核心逻辑在该方法中完成
4、接着执行refresh()方法中的obtainFreshBeanFactory()方法,该方法主要作用就是获取Bean工厂,期间判断是工厂否存在,如果存在则销毁关闭并重新创建,其次加载配置文件中的Bean,并封装成BeanDefinition对象,加载到FactoryBean中
5、紧接着执行refresh()方法中的prepareBeanFactory(beanFactory)方法,该方法主要设置Bean工厂一些属性,比如:设置类加载器,创建Bean工厂时,忽略哪些接口,需要注册哪些跟环境相关的单例Bean
6、接着执行refresh()方法中的postProcessBeanFactory(beanFactory)方法,该方法是Bean定义加载完毕之后实现,目前方法为空实现,留给开发人员进行自定义扩展,比如在BeanFactory加载完所有的Bean定义之后,想要修改某个bean的定义信息,可以通过重写这个方法实现
/**
*比如:在xml中配置了<bean id="user"><property name="name" value="wb"></property></bean>
* 如果想在不修改配置文件的情况下修改name的值,可以使用如下的方法:
*/
class MyApplicationContext extends ClassPathXmlApplicationContext{
	public MyApplicationContext(String s){
		super(s);
	}
    @Override
	protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		BeanDefinition beanDefinition = beanFactory.getBeanDefinition("user");
		PropertyValue propertyValue=new PropertyValue("name", "www.so.com");
							 
        beanDefinition.getPropertyValues().addPropertyValue(propertyValue);
    }
}
						 }
7、接着执行refresh()方法中的invokeBeanFactoryPostProcessors(beanFactory)方法,调用BeanFactory的后置处理器,执行BeanFactoryPostProcessors后置处理器及其子接口           BeanDefinitionRegistryPostProcessor,其中执行BeanDefinitionRegistryPostProcessor
接口的postProcessBeanDefinitionRegistry方法,会扫描指定包下面的标有注解的类,然后将
其封装成BeanDefinitionHolder对象,存放到集合中
8、接着执行refresh()方法中的registerBeanPostProcessors(beanFactory)方法,该方法注册所有的Bean的后置处理器,将所有实现了BeanPostProcessors接口的类加载到BeanFactory中,Spring容器允许BeanPostProcessors在容器初始化前后添加自己的逻辑处理
9、接着执行refresh()方法中的initMessageSource()、initApplicationEventMulticaster()、onRefresh()、registerListeners()方法,主要就是初始化ApplicationContext的MessageSource、初始化事件派发器、注册事件监听器等操作
10、接着执行refresh()方法中的finishBeanFactoryInitialization(beanFactory)方法,该方法会初始化所有剩余的单实例Bean(没有使用懒加载的Bean),也是整个Spring IOC的核心,然后进入该方法主要看下里面到底在做什么?
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
		// 1. 初始化此上下文的转换服务,用来自定义将Spring中的某个Bean的属性从一个类型转换到另外一个类型.
		//    判断Bean工厂中是否存在名称为conversionService的转换服务bean,如果存在而且类型为ConversionService,则获取该Bean实例,并将其设置到BeanFactory中
		/**
		 * 例如:
		 * (1)有如下的javaBean:
		 * public class Person {
		 *     public String name;
		 *     public Date birthday;
		 *     ...
		 * }
		 * (2)有如下的xml配置:
		 * <bean name="person" class="com.wb.test.Person">
		 *     <property name="name" value="wangbing"/>
		 *     <property name="birthday" value="1999-03-03"/>
		 * </bean>
		 * (3)有如下的测试类:
		 * ApplicationContext acx = new ClasspathXmlApplicationContext("test.xml");
		 * Person person = (Person) acx.getBean("person");
		 * System.out.println(person.name);
		 * System.out.println(person.birthday); // 改行会报错,提示字符串类型不能转换为日期类型
		 *
		 * (4)可以通过定义如下名称的bean,将某种类型的属性值转换为另外一种类型.
		 * <bean name="conversionService" class="com.wb.test.MyConversionService" />
		 * public class MyConversionService implements ConversionService {
		 *    // 实现是否能转换以及具体转换的方法。
		 *	  public boolean canConvert(Class<?> sourceType, Class<?> targetType) {}
		 *	  public boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType) {}
		 *    public <T> T convert(Object source, Class<T> targetType) {}
		 *    // 可以在该方法中实现转换逻辑。如果源类型sourceType是String类型的话,将其转换为Date类型返回。
		 *    public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {}
		 * }
		 */
		// 2.在Spring中,如果需要配置自定义的转换器,还可以直接利用Spring提供的ConversionServiceFactoryBean来完成。自己只需要实现具体的转换逻辑即可
		/**
		 * (1)配置conversionService对应的工厂Bean:
		 * <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
		 *     <property name="converters">
		 *			<bean class="com.wb.test.MyConverter"/>
		 *     </property>
		 * </bean>
		 * (2)然后自己去实现Converter即可:
		 *  public class MyConverter implements Converter<String,Date> {
		 *		@Override
		 *		public Date convert(String source) {
		 *			DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
		 *			try {
		 *				return format.parse((String) source);
		 *			} catch (ParseException e) {
		 *				e.printStackTrace();
		 *			}
		 *			return null;
		 *		}
		 *	}
		 */
		if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME)
				&& beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
			beanFactory.setConversionService(beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
		}
		/**
		 * 如果beanFactory之前没有注册嵌入值解析器,则注册默认的嵌入值解析器,
		 *  主要用于注解属性值的解析例如:@Value("${app.name}")。
		 */
		// 值解析器设置的地方:在调用invokeBeanfactoryPostProcessor方法的时候,通过PropertySourcesPlaceholderConfigurer的后置处理方法设置进去的
		if (!beanFactory.hasEmbeddedValueResolver()) {
			// 调用resolvePlaceholders方法解析strVal对应的值
			beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
		}
		/**
		 * 初始化所有实现了LoadTimeWeaverAware接口的子类,用于类在加载进入jvm之前,动态增强类
		 *  这特别适用于Spring的JPA支持,其中load-time weaving加载织入对JPA类转换非常必要
		 */
		String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
		for (String weaverAwareName : weaverAwareNames) {
			getBean(weaverAwareName);
		}

		// 停止使用临时的类加载器.
		beanFactory.setTempClassLoader(null);

		// 缓存(冻结)所有的BeanName(注册的bean定义不会被修改或进一步做处理了,因为下面马上要创建Bean的实例对象了)
		beanFactory.freezeConfiguration();

		// 初始化所有的单实例Bean,包括创建单实例bean的全部过程
		beanFactory.preInstantiateSingletons();
	}
10.1、我们主要看最后一个方法preInstantiateSingletons(),该方法主要初始化所有的单实例Bean,包括创建单实例bean的全部过程
@Override
	public void preInstantiateSingletons() throws BeansException {
		if (logger.isTraceEnabled()) {
			logger.trace("Pre-instantiating singletons in " + this);
		}

		// 创建BeanDefinitionNames的副本BeanNames用于后续的遍历,以允许init等方法注册新的bean定义.
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

		// 遍历所有的beanNames,触发所有非懒加载单例bean的初始化,即:创建所有的单实例Bean
		for (String beanName : beanNames) {
			// 获取beanName对应的MergedBeanDefinition.
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			// 如果bd对应的Bean实例满足:(不是抽象类 && 是单例 && 不是懒加载)
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {

				// 判断BeanName对应的Bean实例是否是FactoryBean.
				if (isFactoryBean(beanName)) {
					// 通过beanName获取FactoryBean的实例,factoryBean的名称是:"&" + beanName
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
					if (bean instanceof FactoryBean) {
						final FactoryBean<?> factory = (FactoryBean<?>) bean;
						boolean isEagerInit;
						// 判断这个FactoryBean是否需要紧急初始化.
						// System.getSecurityManager()方法是获取系统权限管理器,Java为了防止恶意代码执行(修改,删除操作系统文件),做了权限管理,
						//   默认的安全管理器配置文件是: $JAVA_HOME/jre/lib/security/java.policy
						/**
						 * 在做访问控制决定时,如果遇到通过调用不带上下文参数(请参阅下文,以获取关于上下文参数的信息)的 doPrivileged 标记为“特权”的调用方,
						 *  则 checkPermission 方法将停止检查。如果该调用方的域具有指定的权限,则不进行进一步检查,并且 checkPermission 正常返回,
						 *  指示允许所请求的访问。如果该域不具有指定的权限,则通常抛出异常。
						 *
						 *  AccessController.doPrivileged()方法的例子:
						 *  假设有这样一种情况:A程序想在 C:\\Users\\Jack\\Desktop\\test1  这个目录中新建一个文件,但是它没有相应的权限,
						 *   但是它引用了另外一个Jar包B,刚好B有权限在C:\\Users\\Jack\\Desktop\\test1目录中新建文件,
						 *   还有更巧的是B在新建文件的时候采用的是AccessController.doPrivileged方法进行的,这种情况下,A就可以调用B的创建文件的方法进行创建文件了。
						 */
						if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
							isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
											((SmartFactoryBean<?>) factory)::isEagerInit,
									getAccessControlContext());
						}
						else {
							isEagerInit = (factory instanceof SmartFactoryBean &&
									((SmartFactoryBean<?>) factory).isEagerInit());
						}
						if (isEagerInit) {
							// 如果需要紧急初始化,则通过beanName获取Bean的实例.
							getBean(beanName);
						}
					}
				}
				else {
					// 如果BeanName对应的Bean实例不是FactoryBean,则通过BeanName去获取Bean实例.
					getBean(beanName);
				}
			}
		}

从上面代码中可以看到,该方法首先会遍历所有的beanNames,获取beanName对应的MergedBeanDefinition对象,然后判断bd对应的Bean实例是否满足(不是抽象类&&是单例&&不是懒加载),最终都会调用getBean()方法去获取Bean实例

10.1.1、我们进入getBean()方法,该方法中直接调用doGetBean()方法,直接进入doGetBean()方法,看到以下代码
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
		// 获取真正的BeanName。主要包括:(1) 去掉FactoryBean名称前面的&前缀;(2) bean别名解析;
		final String beanName = transformedBeanName(name);
		Object bean;

		// 先尝试从缓存中获取单实例Bean,如果能获取到,说明已经被创建过
		//   注意:如果是通过FactoryBean方式创建对象。在根据名称获取目标bean对象(非FactoryBean实例)时,此处返回的sharedInstance是FactoryBean对象
		Object sharedInstance = getSingleton(beanName);
		/**
		 * 当组件实现了FactoryBean接口,并重写了getObject方法时。在从容器中获取bean的时候,sharedInstance就是容器中返回的bean对象
		 * 此时sharedInstance不为空,就会调用getObjectForBeanInstance方法,这个方法内部会调用子类重写的getObject方法.
 		 */
		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 + "'");
				}
			}
			// 获取bean对象,包括使用FactoryBean来创建bean的逻辑.
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}
		else {
			// 如果当前创建的是单实例类型的bean,则尝试解决循环依赖,此处仅仅只是一个校验;如果当前的多实例bean正在创建中,而且存在循环依赖,直接抛出异常
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}
			// 获取Bean的父工厂? 在Spring和SpringMVC整合之后,会存在着父子容器问题
			// TODO 父子容器处理
			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);
				}
			}

			// 标记Bean已经被创建,防止多线程时,Bean可能会被创建多个,就不是单实例了
			if (!typeCheckOnly) {
				// 将beanName对应的bean定义从mergedBeanDefinitions中移除,并将beanName添加到alreadyCreated集合中.
				markBeanAsCreated(beanName);
			}

			try {
				// 获取合并之后的Bean定义
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);

				// 校验bean对应的类是否为抽象的,如果bean对应的类标注了抽象,直接会抛出异常
				checkMergedBeanDefinition(mbd, beanName, args);

				/**
				 * 获取当前Bean所依赖的其他Bean
				 * 例如:<bean class="com.wb.beans.User" scope="prototype" depends-on="book,football" />,里面的depends-on就是依赖的bean
 				 */
				String[] dependsOn = mbd.getDependsOn();

				// 如果有依赖的Bean
				if (dependsOn != null) {
					for (String dep : dependsOn) {
						// 判断是否存在着循环依赖. a->b b->c c->a这种情况
						/**
						 * 该步骤里面会去解决bean之间的循环依赖,例如如下的bean依赖情况:
						 *
						 * <bean name="classA" class="com.wb.spring.finishBeanFactoryInitialization.domain.ClassA" depends-on="classB"></bean>
						 * <bean name="classB" class="com.wb.spring.finishBeanFactoryInitialization.domain.ClassB" depends-on="classA"></bean>
						 *
						 * 通过acx.getBean("classA");去获取classA对应的bean时,就会提示循环依赖异常。
						 */
						if (isDependent(beanName, dep)) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
						}
						// 维护依赖和被依赖的bean之间的关联关系,Map<String,Set<String>> dependentMap
						registerDependentBean(dep, beanName);
						try {
							// 先去创建当前bean所依赖的其他bean对象
							getBean(dep);
						}
						catch (NoSuchBeanDefinitionException ex) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
						}
					}
				}

				// bean定义如果是单例的,则调用createBean方法进行单实例bean的创建.
				if (mbd.isSingleton()) {
					// 此处的lambda表达式为:ObjectFactory的getObject方法
					sharedInstance = getSingleton(beanName, () -> {
						try {
							/**
							 * 创建对象并初始化,Spring用来创建Bean实例的核心方法
							 *  此处调用的子类AbstractAutowireCapableBeanFactory的createBean方法.
							 */
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							// 如果创建单实例bean失败,则会删除关于该bean的一切信息,包括三级缓存和已经注册的bean集合中有关该bean的信息
							destroySingleton(beanName);
							throw ex;
						}
					});
					/**
					 * 从bean的实例中获取对象.上述创建出来的bean对象sharedInstance只代表了bean的初始状态,
					 *   并不一定是我们最终需要的bean。
					 *
					 * 举个例子,假如我们需要对工厂bean进行处理,那么这里得到的其实是工厂bean的初始状态,
					 *   但是我们真正需要的是工厂bean中定义的 factory-method方法中返回的bean,
					 *   而getObjectForBeanInstance方法就是完成这个工作的。
					 *
					 *
					 *   真实作用:如果一个类实现了FactoryBean接口,则上述bean创建完成之后,其实只是创建好了工厂bean,但是真实的应用
					 *    bean还未创建,此处将会回调FactoryBean的getObject自定义方法进行应用bean的创建工作。
					 */
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}
				// 当前需要创建的bean如果是多例
				else if (mbd.isPrototype()) {
					// 创建多实例bean
					Object prototypeInstance;
					try {
						// 进行多实例bean创建之前的准备工作,将当前正在创建的多实例bean的名称添加到prototypesCurrentlyInCreation中.
						beforePrototypeCreation(beanName);
						// 创建多实例对象,和创建单实例bean使用的是同一个方法
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
						// 从prototypesCurrentlyInCreation【ThreadLocal】中移除
						afterPrototypeCreation(beanName);
					}
					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}
				// 未明确指定将要创建的bean是单例的还是多例的
				else {
					String scopeName = mbd.getScope();
					// 从bean定义中获取bean的scope信息,如果bean的scope信息为null,也就是随意设置的scope,直接抛出异常
					final Scope scope = this.scopes.get(scopeName);
					if (scope == null) {
						throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
					}
					try {
						// 根据指定的scope获取bean实例
						Object scopedInstance = scope.get(beanName, () -> {
							// 初始化之前准备工作,将bean的名称添加到prototypesCurrentlyInCreation
							beforePrototypeCreation(beanName);
							try {
								// 创建bean实例
								return createBean(beanName, mbd, args);
							}
							finally {
								// 从prototypesCurrentlyInCreation中移除
								afterPrototypeCreation(beanName);
							}
						});
						bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
					}
					catch (IllegalStateException ex) {
						throw new BeanCreationException(beanName,
								"Scope '" + scopeName + "' is not active for the current thread; consider " +
								"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
								ex);
					}
				}
			}
			catch (BeansException ex) {
				cleanupAfterBeanCreationFailure(beanName);
				throw ex;
			}
		}

首先根据beanName调用getSingleton(beanName)方法,尝试从单例池中进行获取,以下是getSingleton()方法核心代码,也是利用三级缓存解决循环依赖的主要逻辑

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		// 根据beanName从单实例对象缓存中获取单例对象(singletonObjects为一个ConcurrentHashMap,就是用来保存所有的单实例Bean的,
		//   key:beanName value:beanInstance) 相当于一级缓存
		Object singletonObject = this.singletonObjects.get(beanName);
		// 如果缓存中不存在,而且beanName对应的单实例Bean正在创建中.
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			// 加锁操作.
			synchronized (this.singletonObjects) {
				// 从早期单实例对象缓存中获取单例对象(之所以称为单实例早期对象,
				//   是因为earlySingletonObjects里面的对象都是通过提前曝光的ObjectFactory创建出来的,还未进行属性的填充)
				singletonObject = this.earlySingletonObjects.get(beanName);


				// 如果早期单实例对象缓存中没有,而且允许创建早期单实例对象引用
				if (singletonObject == null && allowEarlyReference) {
					// 则从单例工厂缓存中获取BeanName对应的单例工厂.
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						// 如果存在着单例对象工厂,则通过工厂创建一个单例对象,
						// 调用的是:addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean))中的拉姆达表达式
						singletonObject = singletonFactory.getObject();
						// 将通过单例对象工厂创建的单例对象放入到早期单例对象缓存中,这个早期对象指的是一个空的未完成属性赋值和初始化的对象。
						this.earlySingletonObjects.put(beanName, singletonObject);
						// 移除该beanName对应的单例对象工厂,因为该单例工厂已经创建了一个实例对象,并且放入到earlySingletonObjects缓存中了,
						//  所以,后续通过beanName获取单例对象,可以通过earlySingletonObjects缓存获取到,不需要再用到该单例工厂.
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}

如果从单例池中获取到,直接返回,如果获取不到,则回到doGetBean()方法中继续执行后面逻辑,获取合并之后的BeanDefinition对象,进行校验,如果不是抽象的,则接着获取当前Bean所依赖的其他Bean,如果依赖其他Bean,则通过getBean(dep)先获取所依赖的Bean,之后的逻辑就是真正创建当前需要的Bean

接着判断当前需要创建的Bean是否是单例的,如果是,则调用getSingleton(beanName, 拉姆达表达式),以下代码:

sharedInstance = getSingleton(beanName, () -> {
						try {
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							destroySingleton(beanName);
							throw ex;
						}
					});

​​​​​​​这段代码执行逻辑简单说一下哈:其中getSingleton()方法首先会从单例缓存中尝试获取beanName对应的实例对象,如果获取不到就会进入加锁的代码块中。在这个加锁的代码块中,getSingleton方法会再次尝试获取beanName对应的实例对象,如果获取不到则调用getSingletonObject方法获取该单例实例,getSingletonObject方法会调用getSingleton方法的第二个参数lambda表达式中的代码createBean()方法来创建并初始化beanName对应的实例对象,以下是createBean()方法中的核心代码:

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

		if (logger.isTraceEnabled()) {
			logger.trace("Creating instance of bean '" + beanName + "'");
		}
		// 获取bean的定义信息
		RootBeanDefinition mbdToUse = mbd;

		// 解析bean的类型,使用类加载器真实加载Bean的Class
		Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
			mbdToUse = new RootBeanDefinition(mbd);
			mbdToUse.setBeanClass(resolvedClass);
		}
		try {
			// 对lookup-method和replaced-method指定的方法进行预处理.
			// 主要是标记bean中是否有重载方法。如果一个类有多个重载方法,在后面真正调用或者增强的时候,还需要根据参数类型和参数个数判断调用的哪一个方法,
			// 此处相当于是提前处理。对于只有一个方法的bean,直接标记为无重载方法.
			//  使用的地方:该处设置完标志位之后,在后期的实例化过程中使用cglib实例化策略的时候会使用到。
			mbdToUse.prepareMethodOverrides();
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
					beanName, "Validation of method overrides failed", ex);
		}
		try {
			// 在真正创建Bean之前,执行bean实例化之前的一些工作,可以在此处生成自定义的代理对象.
			// 通过实现InstantiationAwareBeanPostProcessor接口来进行自定义扩展,生成自定义的代理对象
			//   可参考:【示例代码:com.wb.spring.instantiationaware.MyInstantiationAwareBeanPostProcessor】
			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 {
			// 执行创建Bean的操作
			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定义信息BeanDefinition,解析Bean的类型,使用类加载器加载Bean的Class,之后调用doCreateBean()执行Bean的创建,Bean的实例、Bean的初始化以及属性赋值等操作基本都是在该方法中完成,以下是doCreateBean()方法的核心代码:

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

		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			// 删除之前工厂bean缓存中的工厂bean对象,重新进行实例化.
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		// 创建Bean的实例,并且包装为一个包装对象返回.
		if (instanceWrapper == null) {
			// 使用策略方法创建实例,包括:工厂方法,构造函数注入,简单初始化.
			// TODO 里面调用的方法超级长
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		// 获取新创建的bean对象和对应的class
		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) {
			// 如果还未执行MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition方法
			if (!mbd.postProcessed) {
				try {
					// 依次调用所有MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition方法,用来处理类中使用注解标注的属性,并放入到缓存中.
					/**
					 * 其中包括了
					 * 	【AutowiredAnnotationBeanPostProcessor】,  用来处理@Autowired,@Value,@Inject注解
					 * 	【CommonAnnotationBeanPostProcessor】,    用来处理@Resource注解
					 * 	【RequiredAnnotationBeanPostProcessor】, 用来处理@Required注解
					 * 	【InitDestroyAnnotationBeanPostProcessor】,用来处理@Predestroy和@PostConstruct注解
					 * 	【ScheduledAnnotationBeanPostProcessor】,用来处理@Scheduled注解
					 * 		等后置处理器
					 */
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				mbd.postProcessed = true;
			}
		}
		/**
		 * 当前的bean是单例的 && 允许bean之间的循环依赖 && bean正在创建中
		 */
		boolean earlySingletonExposure = (mbd.isSingleton()
				&& this.allowCircularReferences
				&& isSingletonCurrentlyInCreation(beanName));
		// 判断是否需要提前暴露自己。如果需要提前暴露,会将创建完但未填充属性和初始化的bean放入到singletonFactories中,用来解决循环依赖.
		// 		Spring中的单实例Bean,而且是使用属性注入的方式,默认支持循环依赖的;如果是prototype类型的,默认不支持循环依赖
		//     如果是单例bean,而且使用构造器注入的方式,默认不支持循环依赖,可在构造器上添加@Lazy注解,让依赖的属性延迟初始化来解决
		//     如果是单例bean和prototype类型的bean混用,则如果先创建单例,可以成功,如果先创建prototype类型的bean,则会失败
		if (earlySingletonExposure) {
			if (logger.isTraceEnabled()) {
				logger.trace("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			/**
			 * getEarlyBeanReference: 是用来获取到被SmartInstantiationAwareBeanPostProcessor后处理器处理过的刚刚实例化结束的bean对象
			 *
			 * addSingletonFactory: 是用来将刚刚初始化的bean对象放入到singletonFactories中,singletonFactories是个map集合,
			 *  key: bean的名称,value: 是一个ObjectFactory,当存在着循环依赖时,可以通过ObjectFactory.getObject方法获取到刚刚实例化的bean对象
			 */
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}
		/** 初始化单实例bean。 包括:填充属性及执行初始化方法 */
		Object exposedObject = bean;
		try {
			/**
			 * 【依赖注入】
			 * 填充的属性包括:普通属性和使用@Autowired和@Resource注解标注的引用类型属性的赋值。使用了反射操作set方法完成赋值.
			 *
			 * eg: 重点操作举例:
			 * 		【创建完成Bean之后,填充Bean的属性,填充过程中会调用InstantiationAwareBeanPostProcessorAdaptor类的postProcessProperties方法】
			 */
			populateBean(beanName, mbd, instanceWrapper);

			/**
			 * 完成Bean的初始化(执行afterPropertiesSet和init-method)
			 * 		注意:会调用@PostConstruct标注的方法,这个方法是在Bean创建完成,而且属性填充完成之后,才会被调用
			 */
			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 " +
								"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
					}
				}
			}
		}
		try {
			/**
			 * 注册bean的销毁方法,如果bean不是prototype类型,而且requiresDestruction方法返回true
			 *  则会将当前的bean放入到一个需要被销毁的map集合中.
			 */
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
		}
		return exposedObject;
	}

该方法中首先调用createBeanInstance()创建Bean的实例,对应的代码如下,基本每行都有注释,这里不过多赘述

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
		// 解析Bean的Class类型
		Class<?> beanClass = resolveBeanClass(mbd, beanName);

		// 如果Bean不是public,而且是不允许共有权限访问,直接抛出异常.
		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());
		}

		/**
		 * 通过指定的回调方法去创建bean实例,Spring5.0版本之后新增的方法。
		 *  可以通过实现BeanFactoryPostProcessor接口来进行扩展,设置自定义的Supplier,通过自定义supplier实例化对象
		 */
		// 可参考:【示例代码:com.wb.spring.supplier.SupplierBeanFactoryPostProcessor】
		Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
		if (instanceSupplier != null) {
			return obtainFromSupplier(instanceSupplier, beanName);
		}

		/**
		 * 如果当前bean指定了对应的工厂方法,则通过工厂方法去创建bean实例
		 *   底层会获取工厂方法【静态工厂方法|实例化方法】--> 然后解析方法入参 --> 然后执行反射调用创建实例 --> 封装为包装对象返回.
		 *
		 *   fixme: 该方法的实现特别长 230行左右的代码
		 */
		if (mbd.getFactoryMethodName() != null) {
			// 通过工厂方法创建实例,可参考:【示例代码:com.wb.spring.factorymethod.InstanceFactoryMethod,com.wb.spring.factorymethod.StaticFactoryMethod】
			return instantiateUsingFactoryMethod(beanName, mbd, args);
		}

		// Shortcut when re-creating the same bean...
		boolean resolved = false;
		boolean autowireNecessary = false;
		// 原型(prototype),多次获取的时候会走该分支
		if (args == null) {
			synchronized (mbd.constructorArgumentLock) {
				// 因为一个类可能由多个构造函数,所以需要根据配置文件中配置的参数或传入的参数来确定最终调用的构造函数。
				// 因为判断过程会比较,所以spring会将解析、确定好的构造函数缓存到BeanDefinition中的resolvedConstructorOrFactoryMethod字段中。
				// 在下次创建相同时直接从RootBeanDefinition中的属性resolvedConstructorOrFactoryMethod缓存的值获取,避免再次解析
				if (mbd.resolvedConstructorOrFactoryMethod != null) {
					resolved = true;
					// 表示构造函数的参数是否已经解析妥当
					autowireNecessary = mbd.constructorArgumentsResolved;
				}
			}
		}
		if (resolved) {
			// 如果构造函数的参数已经解析妥当
			if (autowireNecessary) {
				// 则通过构造函数完成实例的创建
				return autowireConstructor(beanName, mbd, null, null);
			}
			else {
				// 使用默认的bean对象创建策略进行bean对象的创建  ***【此处使用了策略设计模式】***
				return instantiateBean(beanName, mbd);
			}
		}

		/** 推断构造方法,获取候选的用来创建bean对象的构造函数 */
		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
		// 获取到了构造函数 || 注入模式为使用构造函数 || bean定义中指定了带参数的构造函数 || 创建bean对象时的入参args[参数列表对应的值列表]不为null
		if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
			// 使用构造函数及入参进行bean对象的创建
			return autowireConstructor(beanName, mbd, ctors, args);
		}

		/** 获取指定的用来创建bean对象的默认构造函数 */
		ctors = mbd.getPreferredConstructors();
		if (ctors != null) {
			return autowireConstructor(beanName, mbd, ctors, null);
		}

		/**
		 * 如果上述情况都没有:没有创建bean的回调方法 && 没有工厂方法 && 构造函数的参数未解析完毕 && 没有预先指定的默认构造函数
		 *   则使用默认策略来创建bean对象
		 */
		return instantiateBean(beanName, mbd);
	}

通过createBeanInstance()创建好Bean的实例并返回,接着执行doCreateBean()方法中的逻辑,接下来就是属性赋值,属性赋值是通过populateBean()方法完成,核心逻辑如下:

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.
		// 是否需要继续进行属性填充.
		boolean continueWithPropertyPopulation = true;

		/**
		 * 首先判断bean在初始化的时候是否需要进行属性值的注入.
		 *
		 * 可以通过扩展InstantiationAwareBeanPostProcessor接口来实现是否进行属性值注入的判断逻辑。
		 * 如下,直接返回false,则所有标注@Autowired注解的都不会进行依赖注入
		 *
		 * @Component
		 * class MyProcessor implements InstantiationAwareBeanPostProcessor {
		 * 	   @Override
		 *     public boolean postProcessAfterInstantiation(Object bean, String beanName) {
		 *         return false;
		 *     }
		 * }
		 */
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
						continueWithPropertyPopulation = false;
						break;
					}
				}
			}
		}
		// 如果不需要进行属性的依赖注入,则直接返回.
		if (!continueWithPropertyPopulation) {
			return;
		}

		/** 获取当前正在实例化的bean的所有属性及值,类型为map: key:属性名称,value:值或者引用 */
		PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

		/** 如果bean定义中指定的注入类型为通过名称或者通过类型注入,则解析出依赖的属性值或引用。但是该步骤不会进行属性的赋值操作 */
		if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
			/** 如果是按照名称进行自动注入,通过属性名称获取依赖的属性值或者引用 */
			if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {
				// TODO WangBing ???
				autowireByName(beanName, mbd, bw, newPvs);
			}
			/** 如果是按照类型进行自动注入,则通过属性的类型获取依赖的属性值或者引用 */
			if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
				// TODO WangBing ???
				autowireByType(beanName, mbd, bw, newPvs);
			}
			pvs = newPvs;
		}

		// 当前bean是否有InstantiationAwareBeanPostProcessor类型的后置处理器
		boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
		// 自动装配时需要进行依赖的检查
		boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

		PropertyDescriptor[] filteredPds = null;
		// 如果存在着InstantiationAwareBeanPostProcessor【继承自BeanPostProcessor】类型的后置处理器
		if (hasInstAwareBpps) {
			if (pvs == null) {
				pvs = mbd.getPropertyValues();
			}
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				// 如果是InstantiationAwareBeanPostProcessor的实例
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					// 则依次执行后置处理器的postProcessProperties,首先使用postProcessProperties,获取属性值
					PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
					if (pvsToUse == null) {
						if (filteredPds == null) {
							filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
						}
						// 如果通过postProcessProperties未获取到属性值,再通过postProcessPropertyValues获取属性值
						pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
						if (pvsToUse == null) {
							return;
						}
					}
					pvs = pvsToUse;
				}
			}
		}
		// 如果需要进行依赖的检查【包括简单类型和对象类型】
		if (needsDepCheck) {
			if (filteredPds == null) {
				/**
				 * 通过一些过滤条件过滤掉不需要自动注入属性值的属性
				 * 其中包括:refresh()方法的prepareBeanFactory步骤中所忽略的接口.
 				 */
				filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
			}
			/**
			 * 检查属性值的依赖。如果bean中的属性有setter方法,但是属性名称没有包含在属性值列表中,将会抛出异常
			 */
			checkDependencies(beanName, mbd, filteredPds, pvs);
		}
		/** 如果解析出来的依赖属性值集合不为空,则通过applyPropertyValues进行属性值的填充 */
		if (pvs != null) {
			applyPropertyValues(beanName, mbd, bw, pvs);
		}
	}

属性赋值之后,紧接着进行初始化,调用initializeBean()方法进行初始化,判断Bean是否实现了Aware接口、BeanPostProcessor接口等等,顶部流程图中都有详细解释,以下是初始化的核心逻辑:

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 {
			/**
			 * 调用Bean实现的Aware接口的方法,主要包括下面三个接口
			 * BeanNameAware ----> setBeanName()
			 * BeanClassLoaderAware ----> setBeanClassLoader()
			 * BeanFactoryAware  ----> setBeanFactory()
			 */
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			/** 调用Bean对象的postProcessBeforeInitialization方法,此处会执行标注@PostConstruct注解的方法 */
			// 此处会调用ApplicationContextAwareProcessor执行其他的aware方法.
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}
		try {
			/**
			 * 执行Bean的初始化方法:
			 *
			 * 1.先判断Bean是否实现了InitializingBean接口,如果实现了InitializingBean接口,则调用Bean对象的afterPropertiesSet方法;
			 * 2.然后判断Bean是否有指定init-method方法,如果指定了init-method方法,则调用bean对象的init-method指定的方法.
			 */
			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()) {
			/**
			 * 调用Bean对象的postProcessAfterInitialization方法
			 *
			 * 如果需要创建代理,在该步骤中执行postProcessAfterInitialization方法的时候会去创建代理
			 * 调用AbstractAutoProxyCreator类的postProcessAfterInitialization方法,然后调用wrapIfNecessary方法去创建代理.
			 *
			 *
			 * 另外还有一些Aware接口,也会在该步骤中执行,例如:ApplicationContextAwareProcessor后置处理器,对应的setApplicationContext方法会被执行.
			 */
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}
		return wrappedBean;
	}

初始化之后,通过registerDisposableBeanIfNecessary()方法注册Bean的回调,以下是该方法核心逻辑:

protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
		AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
		// 如果不是多例的 && 需要被销毁
		if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
			// 如果是单实例Bean
			if (mbd.isSingleton()) {
				// 如果当前的bean不是空Bean && (存在着销毁方法 || (实现了DestructionAwareBeanPostProcessor接口 && requiresDestruction后置方法返回值为true))
				// 如果存在着(销毁方法 || 需要被销毁) && 是单例Bean   则会将当前的bean保存到一个disposableBeans对应的Map集合中,map的key为bean名称,value为要被销毁的bean
				registerDisposableBean(beanName,
						new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
			}
			else {
				// 除了prototype之外其他作用域的Bean,则注册自定义的bean销毁回调方法
				Scope scope = this.scopes.get(mbd.getScope());
				if (scope == null) {
					throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
				}
				scope.registerDestructionCallback(beanName,
						new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
			}
		}
	}

至此Bean创建完成,可以正常使用,如果当Spring容器关闭的时候,首先判断是否实现了DisableBean接口,如果实现了会调用自定义的销毁方法进行销毁,至此整个Bean的生命周期就完成了!

总结:

        以上就是整个Spring Bean从容器创建到实例化、再到属性赋值、再到初始化、再到注册Destruction回调,最后到Bean的销毁完整过程,中间有些地方会比较绕,利用debug模式多调试过几遍流程就可以理解了!

  • 9
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值