我的编程空间,编程开发者的网络收藏夹
学习永远不晚

SpringBoot源码之Bean的生命周期是什么

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

SpringBoot源码之Bean的生命周期是什么

本文小编为大家详细介绍“SpringBoot源码之Bean的生命周期是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“SpringBoot源码之Bean的生命周期是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

入口方法为SpringApplication#run()

SpringApplication#run()

public ConfigurableApplicationContext run(String... args) {long startTime = System.nanoTime();DefaultBootstrapContext bootstrapContext = createBootstrapContext();ConfigurableApplicationContext context = null;configureHeadlessProperty();SpringApplicationRunListeners listeners = getRunListeners(args);listeners.starting(bootstrapContext, this.mainApplicationClass);try {ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);Banner printedBanner = printBanner(environment);context = createApplicationContext();context.setApplicationStartup(this.applicationStartup);prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);refreshContext(context);afterRefresh(context, applicationArguments);Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);if (this.logStartupInfo) {new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);}listeners.started(context, timeTakenToStartup);callRunners(context, applicationArguments);}catch (Throwable ex) {if (ex instanceof AbandonedRunException) {throw ex;}handleRunFailure(context, ex, listeners);throw new IllegalStateException(ex);}try {if (context.isRunning()) {Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);listeners.ready(context, timeTakenToReady);}}catch (Throwable ex) {if (ex instanceof AbandonedRunException) {throw ex;}handleRunFailure(context, ex, null);throw new IllegalStateException(ex);}return context;}

SpringApplication#run()=> SpringApplication#refreshContext(context)=> SpringApplication#refresh(context)=>ConfigurableApplicationContext#refresh()=>AbstractApplicationContext#refresh()

@Overridepublic void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");// Prepare this context for refreshing.prepareRefresh();// Tell the subclass to refresh the internal bean factory.ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// Prepare the bean factory for use in this context.prepareBeanFactory(beanFactory);try {// Allows post-processing of the bean factory in context subclasses.postProcessBeanFactory(beanFactory);StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");// Invoke factory processors registered as beans in the context.invokeBeanFactoryPostProcessors(beanFactory);// Register bean processors that intercept bean creation.registerBeanPostProcessors(beanFactory);beanPostProcess.end();// Initialize message source for this context.initMessageSource();// Initialize event multicaster for this context.initApplicationEventMulticaster();// Initialize other special beans in specific context subclasses.onRefresh();// Check for listener beans and register them.registerListeners();// Instantiate all remaining (non-lazy-init) singletons.finishBeanFactoryInitialization(beanFactory);// Last step: publish corresponding event.finishRefresh();}catch (BeansException ex) {if (logger.isWarnEnabled()) {logger.warn("Exception encountered during context initialization - " +"cancelling refresh attempt: " + ex);}// Destroy already created singletons to avoid dangling resources.destroyBeans();// Reset 'active' flag.cancelRefresh(ex);// Propagate exception to caller.throw ex;}finally {// Reset common introspection caches in Spring's core, since we// might not ever need metadata for singleton beans anymore...resetCommonCaches();contextRefresh.end();}}}

SpringApplication#run()=> SpringApplication#refreshContext(context)=> SpringApplication#refresh(context)=>ConfigurableApplicationContext#refresh()=>AbstractApplicationContext#refresh()=>AbstractApplicationContext#finishBeanFactoryInitialization()=>ConfigurableListableBeanFactory#preInstantiateSingletons()=>DefaultListableBeanFactory#preInstantiateSingletons()

@Overridepublic void preInstantiateSingletons() throws BeansException {if (logger.isTraceEnabled()) {logger.trace("Pre-instantiating singletons in " + this);}// Iterate over a copy to allow for init methods which in turn register new bean definitions.// While this may not be part of the regular factory bootstrap, it does otherwise work fine.List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);// Trigger initialization of all non-lazy singleton beans...for (String beanName : beanNames) {RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {if (isFactoryBean(beanName)) {Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);if (bean instanceof SmartFactoryBean<?> smartFactoryBean && smartFactoryBean.isEagerInit()) {getBean(beanName);}}else {// 此处就是初始化bean的方法getBean(beanName);}}}// Trigger post-initialization callback for all applicable beans...for (String beanName : beanNames) {// 此处就是解决循环依赖的代码Object singletonInstance = getSingleton(beanName);if (singletonInstance instanceof SmartInitializingSingleton smartSingleton) {StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize").tag("beanName", beanName);smartSingleton.afterSingletonsInstantiated();smartInitialize.end();}}}

解决循环依赖的代码如下:

protected Object getSingleton(String beanName, boolean allowEarlyReference) {// 尝试从缓存中获取成品的目标对象,如果存在,则直接返回  Object singletonObject = this.singletonObjects.get(beanName);  // 如果缓存中不存在目标对象,则判断当前对象是否已经处于创建过程中,在前面的讲解中,第一次尝试获取A对象  // 的实例之后,就会将A对象标记为正在创建中,因而最后再尝试获取A对象的时候,这里的if判断就会为true  if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {    synchronized (this.singletonObjects) {      singletonObject = this.earlySingletonObjects.get(beanName);      if (singletonObject == null && allowEarlyReference) {        // 这里的singletonFactories是一个Map,其key是bean的名称,而值是一个ObjectFactory类型的        // 对象,这里对于A和B而言,调用图其getObject()方法返回的就是A和B对象的实例,无论是否是半成品        ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);        if (singletonFactory != null) {          // 获取目标对象的实例          singletonObject = singletonFactory.getObject();          this.earlySingletonObjects.put(beanName, singletonObject);          this.singletonFactories.remove(beanName);        }      }    }  }  return singletonObject;}
  • 一级缓存,singletonObjects 单例缓存,存储已经实例化的单例bean。

  • 二级缓存,earlySingletonObjects 提前暴露的单例缓存,这里存储的bean是刚刚构造完成,但还会通过属性注入bean。

  • 三级缓存,singletonFactories 生产单例的工厂缓存,存储工厂。

解决原理如下:

  • 在第一层中,先去获取 A 的 Bean,发现没有就准备去创建一个,然后将 A 的代理工厂放入“三级缓存”(这个 A 其实是一个半成品,还没有对里面的属性进行注入),但是 A 依赖 B 的创建,就必须先去创建 B;

  • 在第二层中,准备创建 B,发现 B 又依赖 A,需要先去创建 A,去创建 A,因为第一层已经创建了 A 的代理工厂,直接从“三级缓存”中拿到 A 的代理工厂,获取 A 的代理对象,放入“二级缓存”,并清除“三级缓存”;

  • 有了 A 的代理对象,对 A 的依赖完美解决(这里的 A 仍然是个半成品),B 初始化成功。在 B 初始化成功,完成 A 对象的属性注入,然后再填充 A 的其它属性,以及 A 的其它步骤(包括 AOP),完成对 A 完整的初始化功能(这里的 A 才是完整的 Bean)。

  • 将 A 放入“一级缓存”。

SpringApplication#run()=> SpringApplication#refreshContext(context)=> SpringApplication#refresh(context)=>ConfigurableApplicationContext#refresh()=>AbstractApplicationContext#refresh()=>AbstractApplicationContext#finishBeanFactoryInitialization()=>ConfigurableListableBeanFactory#preInstantiateSingletons()=>DefaultListableBeanFactory#preInstantiateSingletons()=>AbstractBeanFactory#getBean() => AbstractBeanFactory#doGetBean()=>AbstractBeanFactory#createBean()=>AbstractAutowireCapableBeanFactory#createBean()=>AbstractAutowireCapableBeanFactory#doCreateBean()

bean的生命周期:

调用InstantiationAwareBeanPostProcessor# postProcessBeforeInstantiation
跟进doCreateBean()

@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.   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 {        // 1.调用InstantiationAwareBeanPostProcessor# postProcessBeforeInstantiation      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 {    // 跟进doCreateBean()      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);     }  }

创建bean实例

跟进populateBean()
跟进initializeBean()

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);     }     if (instanceWrapper == null) {   // 2.创建bean实例       instanceWrapper = createBeanInstance(beanName, mbd, args);     }     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) {        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.markAsPostProcessed();        }     }       // Eagerly cache singletons to be able to resolve circular references     // even when triggered by lifecycle interfaces like BeanFactoryAware.   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()      populateBean(beanName, mbd, instanceWrapper);       // 跟进initializeBean()       exposedObject = initializeBean(beanName, exposedObject, mbd);     }     catch (Throwable ex) {        if (ex instanceof BeanCreationException bce && beanName.equals(bce.getBeanName())) {           throw bce;        }        else {           throw new BeanCreationException(mbd.getResourceDescription(), beanName, ex.getMessage(), 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;  }

调用InstantiationAwareBeanPostProcessor# postProcessAfterInstantiation

注入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;        }     }       if (bw.getWrappedClass().isRecord()) {        if (mbd.hasPropertyValues()) {           throw new BeanCreationException(                 mbd.getResourceDescription(), beanName, "Cannot apply property values to a record");        }        else {           // Skip property population phase for records since they are immutable.           return;        }     }          // 3.调用InstantiationAwareBeanPostProcessor# postProcessAfterInstantiation      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;     }     if (hasInstantiationAwareBeanPostProcessors()) {        if (pvs == null) {          pvs = mbd.getPropertyValues();        }        for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {           PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);           if (pvsToUse == null) {              return;           }           pvs = pvsToUse;        }     }       boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);     if (needsDepCheck) {        PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);        checkDependencies(beanName, mbd, filteredPds, pvs);     }       if (pvs != null) {  // 4.注入属性        applyPropertyValues(beanName, mbd, bw, pvs);     }  }

设置Aware接口的属性

调用BeanPostProcessor的初始化前置方法

先((InitializingBean) bean).afterPropertiesSet(),后调用init-method方法,进行初始化操作

调用BeanPostProcessor的初始化后置方法

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {    // 5.设置Aware接口的属性   invokeAwareMethods(beanName, bean);       Object wrappedBean = bean;     if (mbd == null || !mbd.isSynthetic()) {  // 5.调用BeanPostProcessor的初始化前置方法        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);     }       try {  // 6.调用init-method方法,进行初始化操作        invokeInitMethods(beanName, wrappedBean, mbd);     }     catch (Throwable ex) {        throw new BeanCreationException(              (mbd != null ? mbd.getResourceDescription() : null), beanName, ex.getMessage(), ex);     }     if (mbd == null || !mbd.isSynthetic()) {       // 7. 调用BeanPostProcessor的初始化后置方法      wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);     }       return wrappedBean;  }

读到这里,这篇“SpringBoot源码之Bean的生命周期是什么”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注编程网行业资讯频道。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

SpringBoot源码之Bean的生命周期是什么

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

SpringBoot源码之Bean的生命周期是什么

本文小编为大家详细介绍“SpringBoot源码之Bean的生命周期是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“SpringBoot源码之Bean的生命周期是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知
2023-07-06

SpringBoot源码之Bean的生命周期

spring的bean的生命周期主要是创建bean的过程,一个bean的生命周期主要是4个步骤,实例化,属性注入,初始化,销毁,本文详细介绍了bean的生命周期,感兴趣的小伙伴可以参考阅读
2023-05-15

Spring Bean生命周期源码分析

这篇“Spring Bean生命周期源码分析”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Spring Bean生命周期源码
2023-07-05

Spring Bean的生命周期是什么

这篇“Spring Bean的生命周期是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Spring Bean的生命周期是
2023-07-05

Spring bean的生命周期是什么

Spring bean的生命周期包括以下阶段:1. 实例化(Instantiation):在容器启动时,Spring根据配置信息或注解等方式实例化bean对象。2. 属性赋值(Populate bean properties):Spring
2023-08-24

spring中bean的生命周期是什么

在Spring中,Bean的生命周期包括以下几个阶段:1. 实例化:当Spring容器接收到请求时,根据配置文件或注解等方式,在内存中创建Bean的实例。2. 属性赋值:Spring容器通过依赖注入的方式,将Bean的属性值注入到相应的属性
2023-09-27

Java之Spring Bean作用域和生命周期源码分析

这篇文章主要讲解了“Java之Spring Bean作用域和生命周期源码分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java之Spring Bean作用域和生命周期源码分析”吧!Bea
2023-07-05

spring之Bean的生命周期详解

Bean的生命周期:Bean的定义——Bean的初始化——Bean的使用——Bean的销毁Bean的定义Bean 是 spring 装配的组件模型,一切实体类都可以配置成一个 Bean ,进而就可以在任何其他的 Bean 中使用,一个 Be
2023-05-31

Springboot事件和bean生命周期执行机制是什么

今天小编给大家分享一下Springboot事件和bean生命周期执行机制是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。
2023-07-05

Java之Bean的生命周期实例分析

本篇内容主要讲解“Java之Bean的生命周期实例分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java之Bean的生命周期实例分析”吧!一、什么是生命周期首先理解下什么是生命周期?从创建到
2023-07-02

Spring中Bean的作用域与生命周期是什么

这篇文章主要讲解了“Spring中Bean的作用域与生命周期是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Spring中Bean的作用域与生命周期是什么”吧!一、Bean的作用域通过S
2023-06-22

Spring的Bean初始化过程和生命周期是什么

本篇内容介绍了“Spring的Bean初始化过程和生命周期是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、Spring创建bean的
2023-07-05

Flutter的生命周期是什么

今天小编给大家分享一下Flutter的生命周期是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。一 这里看一下Statef
2023-07-06

Springbean的生命周期是什么

Spring Bean的生命周期可以分为以下几个阶段:实例化(Instantiation):在容器启动时,Spring根据配置信息或注解实例化Bean对象。属性赋值(Population of properties):Spring将通过依赖
2023-10-24

Vue的生命周期是什么

本篇内容主要讲解“Vue的生命周期是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Vue的生命周期是什么”吧!生命周期生命周期的简单介绍1.生命周期又叫做:生命周期回调函数、生命周期函数、生
2023-06-29

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录