前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring之bean的生命周期

Spring之bean的生命周期

作者头像
九转成圣
发布2024-06-06 08:21:31
1070
发布2024-06-06 08:21:31
举报
文章被收录于专栏:csdn

Spring之Bean的生命周期详解

在Spring框架中,Bean的创建和管理是通过Spring容器来完成的。Spring Bean生命周期包括实例化、属性填充、初始化、销毁等多个步骤。本文将详细解析Spring中Bean的生命周期,并重点介绍AbstractAutowireCapableBeanFactory类中的createBean方法及其相关的方法调用。

Bean的生命周期概述

Spring Bean的生命周期分为多个阶段,每个阶段都由特定的方法和机制来完成:

  1. 实例化前准备:解析Bean定义,确定Bean类型。
  2. 实例化:创建Bean实例。
  3. 属性填充:对Bean的各个属性进行依赖注入。
  4. 初始化:执行自定义的初始化方法和Spring的BeanPostProcessor回调。
  5. 使用:Bean已经完全初始化并可以使用。
  6. 销毁:容器关闭时,对Bean进行清理工作,执行销毁方法。

下面我们将通过源码详细解析每个步骤的实现。

createBean方法详解

createBean方法是Spring中创建Bean实例的核心方法。该方法的实现位于AbstractAutowireCapableBeanFactory类中:

代码语言:javascript
复制
@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;

    // 确保bean类已解析并克隆bean定义以防止共享的bean定义中的动态解析类无法存储
    Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
    if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
        mbdToUse = new RootBeanDefinition(mbd);
        mbdToUse.setBeanClass(resolvedClass);
    }

    // 准备方法重写
    try {
        mbdToUse.prepareMethodOverrides();
    } catch (BeanDefinitionValidationException ex) {
        throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", ex);
    }

    try {
        // 在实例化前,给BeanPostProcessors一个返回代理而不是目标bean实例的机会。
        Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
        if (bean != null) {
            return bean;
        }
    } catch (Throwable ex) {
        throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", ex);
    }

    try {
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
        if (logger.isTraceEnabled()) {
            logger.trace("Finished creating instance of bean '" + beanName + "'");
        }
        return beanInstance;
    } catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
        throw ex;
    } catch (Throwable ex) {
        throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
    }
}
1. resolveBeanClass方法

在Bean实例化之前,首先需要解析Bean的类:

代码语言:javascript
复制
protected Class<?> resolveBeanClass(RootBeanDefinition mbd, String beanName, Class<?>... typesToMatch)
      throws CannotLoadBeanClassException {
   try {
      if (mbd.hasBeanClass()) {
         return mbd.getBeanClass();
      }

      if (System.getSecurityManager() != null) {
         return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>) () -> doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
      } else {
         return doResolveBeanClass(mbd, typesToMatch);
      }
   } catch (PrivilegedActionException pae) {
      ClassNotFoundException ex = (ClassNotFoundException) pae.getException();
      throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
   } catch (ClassNotFoundException ex) {
      throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
   } catch (LinkageError err) {
      throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), err);
   }
}
2. prepareMethodOverrides方法

检查和准备Bean定义中定义的方法重写:

代码语言:javascript
复制
public void prepareMethodOverrides() throws BeanDefinitionValidationException {
   if (hasMethodOverrides()) {
      getMethodOverrides().getOverrides().forEach(this::prepareMethodOverride);
   }
}
3. resolveBeforeInstantiation方法

在实例化Bean之前,调用BeanPostProcessor来尝试返回代理对象:

代码语言:javascript
复制
@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
    Object bean = null;
    if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            Class<?> targetType = determineTargetType(beanName, mbd);
            if (targetType != null) {
                bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                if (bean != null) {
                    bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                }
            }
        }
        mbd.beforeInstantiationResolved = (bean != null);
    }
    return bean;
}
3.1 applyBeanPostProcessorsBeforeInstantiation方法

调用InstantiationAwareBeanPostProcessorpostProcessBeforeInstantiation方法:

代码语言:javascript
复制
@Nullable
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
   for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
      Object result = bp.postProcessBeforeInstantiation(beanClass, beanName);
      if (result != null) {
         return result;
      }
   }
   return null;
}
3.2 applyBeanPostProcessorsAfterInitialization方法

调用BeanPostProcessorpostProcessAfterInitialization方法:

代码语言:javascript
复制
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
      throws BeansException {
   Object result = existingBean;
   for (BeanPostProcessor processor : getBeanPostProcessors()) {
      Object current = processor.postProcessAfterInitialization(result, beanName);
      if (current == null) {
         return result;
      }
      result = current;
   }
   return result;
}
4. doCreateBean方法

实际创建Bean实例的主要方法:

代码语言:javascript
复制
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
        throws BeanCreationException {
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    if (instanceWrapper == null) {
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    Object bean = instanceWrapper.getWrappedInstance();
    Class<?> beanType = instanceWrapper.getWrappedClass();
    if (beanType != NullBean.class) {
        mbd.resolvedTargetType = beanType;
    }

    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;
        }
    }

    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));
    }

    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.");
                }
            }
        }
    }

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

    return exposedObject;
}
4.1 createBeanInstance方法

创建Bean实例的方法:

代码语言:javascript
复制
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    // 构造方法自动装配
    Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
        return autowireConstructor(beanName, mbd, ctors, args);
    }

    // 使用工厂方法创建bean
    if (mbd.getFactoryMethodName() != null) {
        return instantiateUsingFactoryMethod(beanName, mbd, args);
    }

    // 默认的无参构造函数实例化
    return instantiateBean(beanName, mbd);
}
4.2 populateBean方法

对Bean的属性进行填充:

代码语言:javascript
复制
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    PropertyValues pvs = mbd.getPropertyValues();

    if (bw == null) {
        if (!pvs.isEmpty()) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
        } else {
            return;
        }
    }

    if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
        MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

        // Add property values based on autowire by name if applicable.
        if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {
            autowireByName(beanName, mbd, bw, newPvs);
        }

        // Add property values based on autowire by type if applicable.
        if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
            autowireByType(beanName, mbd, bw, newPvs);
        }

        pvs = newPvs;
    }

    applyPropertyValues(beanName, mbd, bw, pvs);
}
4.3 initializeBean方法

对Bean进行初始化,包括调用BeanPostProcessor

代码语言:javascript
复制
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
    invokeAwareMethods(beanName, bean);

    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }

    try {
        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()) {
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }

    return wrappedBean;
}
5. registerDisposableBeanIfNecessary方法

注册需要销毁的Bean:

代码语言:javascript
复制
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
    AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
    if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
        if (mbd.isSingleton()) {
            registerDisposableBean(beanName, new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessorCache().destruction, acc));
        } else {
            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, getBeanPostProcessorCache().destruction, acc));
        }
    }
}

详细分析每个步骤

为了更全面地理解Spring Bean的生命周期,我们将详细解析每个步骤,探讨其内部机制和关键方法。

实例化前准备

实例化前的准备工作包括解析Bean的类信息和准备方法重写。这一步骤确保在实例化Bean之前,所有必要的元数据和配置已经到位。

解析Bean的类

解析Bean的类是通过resolveBeanClass方法实现的。该方法负责将Bean定义中的类名解析为实际的Class对象:

代码语言:javascript
复制
protected Class<?> resolveBeanClass(RootBeanDefinition mbd, String beanName, Class<?>... typesToMatch)
      throws CannotLoadBeanClassException {
   try {
      if (mbd.hasBeanClass()) {
         return mbd.getBeanClass();
      }

      if (System.getSecurityManager() != null) {
         return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>) () -> doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
      } else {
         return doResolveBeanClass(mbd, typesToMatch);
      }
   } catch (PrivilegedActionException pae) {
      ClassNotFoundException ex = (ClassNotFoundException) pae.getException();
      throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
   } catch (ClassNotFoundException ex) {
      throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
   } catch (LinkageError err) {
      throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), err);
   }
}

在解析过程中,Spring会检查Bean定义中是否已经包含了Class对象。如果没有,Spring会根据Bean的类名进行加载。这个过程可以在受控的安全环境中进行,以确保在安全管理器启用的情况下也能够正确加载类。

准备方法重写

准备方法重写是通过prepareMethodOverrides方法实现的。该方法会检查Bean定义中是否包含了需要重写的方法,并进行相应的准备工作:

代码语言:javascript
复制
public void prepareMethodOverrides() throws BeanDefinitionValidationException {
   if (hasMethodOverrides()) {
      getMethodOverrides().getOverrides().forEach(this::prepareMethodOverride);
   }
}

方法重写的准备工作包括验证方法签名和确保方法的可访问性。这一步骤对于支持方法重写功能的Bean非常重要,例如使用CGLIB动态代理的Bean。

实例化Bean

实例化Bean是通过调用createBeanInstance方法来实现的。该方法负责根据不同的情况创建Bean实例,包括构造方法自动装配、工厂方法实例化以及默认的无参构造函数实例化。

构造方法自动装配

如果Bean定义中包含构造函数参数,或者需要进行构造函数自动装配,Spring会调用autowireConstructor方法:

代码语言:javascript
复制
protected BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd, Constructor<?>[] chosenCtors, Object[] explicitArgs) {
   return new ConstructorResolver(this).autowireConstructor(beanName, mbd, chosenCtors, explicitArgs);
}

autowireConstructor方法会根据Bean定义中的构造函数参数信息选择合适的构造函数,并通过反射机制创建Bean实例。

工厂方法实例化

如果Bean定义中指定了工厂方法,Spring会调用instantiateUsingFactoryMethod方法:

代码语言:javascript
复制
protected BeanWrapper instantiateUsingFactoryMethod(String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
   return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);
}

工厂方法实例化会根据Bean定义中的工厂方法名,通过反射调用工厂方法创建Bean实例。

默认无参构造函数实例化

如果Bean定义中既没有构造函数参数,也没有工厂方法,Spring会调用instantiateBean方法:

代码语言:javascript
复制
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);
   }
}

该方法会调用默认的无参构造函数创建Bean实例,并返回一个包装了Bean实例的BeanWrapper对象。

属性填充

属性填充是通过populateBean方法来实现的。该方法负责对Bean实例的属性进行依赖注入,包括自动装配和手动指定的属性值。

自动装配

自动装配是通过autowireByNameautowireByType方法来实现的。这些方法会根据Bean定义中的自动装配模式,按照名称或类型进行依赖注入。

手动指定的属性值

如果Bean定义中包含了手动指定的属性值,Spring会调用applyPropertyValues方法将这些属性值设置到Bean实例上:

代码语言:javascript
复制
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
   if (pvs.isEmpty()) {
      return;
   }

   MutablePropertyValues mpvs = (pvs instanceof MutablePropertyValues ? (MutablePropertyValues) pvs : new MutablePropertyValues(pvs));
   List<PropertyValue> original = mpvs.getPropertyValueList();

   TypeConverter converter = getCustomTypeConverter();
   if (converter == null) {
      converter = bw;
   }
   BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);

   // Create a deep copy, resolving any references for values.
   for (PropertyValue pv : original) {
      if (pv.isConverted()) {
         continue;
      }
      Object originalValue = pv.getValue();
      Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
      PropertyValue newPv = new PropertyValue(pv.getName(), resolvedValue);
      newPv.setConverted();
      mpvs.addPropertyValue(newPv);
   }

   bw.setPropertyValues(mpvs);
}

该方法会解析属性值中的依赖项,并将解析后的值设置到Bean实例上。

初始化Bean

初始化Bean是通过initializeBean方法来实现的。该方法会调用一系列的回调方法,包括BeanPostProcessorpostProcessBeforeInitializationpostProcessAfterInitialization方法,以及Bean实例中的初始化方法。

调用BeanPostProcessor回调

BeanPostProcessor回调方法用于在Bean初始化的前后执行一些自定义逻辑,例如代理对象的创建和自定义初始化逻辑的执行。

调用Bean实例的初始化方法

如果Bean实例实现了InitializingBean接口,Spring会调用afterPropertiesSet方法。如果Bean定义中指定了初始化方法,Spring会通过反射调用该方法:

代码语言:javascript
复制
protected void invokeInitMethods(String beanName, Object bean, RootBeanDefinition mbd) throws Throwable {
   boolean isInitializingBean = (bean instanceof InitializingBean);
   if (isInitializingBean) {
      if (System.getSecurityManager() != null) {
         try {
            AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
               ((InitializingBean) bean).afterPropertiesSet();
               return null;
            }, getAccessControlContext());
         } catch (PrivilegedActionException pae) {
            throw pae.getException();
         }
      } else {
         ((InitializingBean) bean).afterPropertiesSet();
      }
   }

   if (mbd != null && bean.getClass() != NullBean.class) {
      String initMethodName = mbd.getInitMethodName();
      if (StringUtils.hasLength(initMethodName) && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName))) {
         invokeCustomInitMethod(beanName, bean, mbd);
      }
   }
}
销毁Bean

销毁Bean是通过注册销毁回调方法来实现的。当Spring容器关闭时,会调用这些销毁回调方法对Bean进行清理工作。

注册销毁回调

注册销毁回调是通过registerDisposableBeanIfNecessary方法来实现的。该方法会根据Bean的作用域和生命周期,注册相应的销毁回调:

代码语言:javascript
复制
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
    AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
    if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
        if (mbd.isSingleton()) {
            registerDisposableBean(beanName, new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessorCache().destruction, acc));
        } else {
            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, getBeanPostProcessorCache().destruction, acc));
        }
    }
}

总结

Spring框架通过一系列复杂的步骤和机制,管理Bean的整个生命周期。理解这些机制有助于开发人员更好地利用Spring框架,编写高效、可维护的代码。通过深入研究AbstractAutowireCapableBeanFactory类中的createBean方法及其相关的内部调用,我们可以清晰地看到Spring是如何创建、初始化和销毁Bean的。

这些机制不仅提供了强大的灵活性和可扩展性,还通过各种回调和扩展点,允许开发人员在Bean的生命周期各个阶段插入自定义逻辑,从而满足各种复杂的应用需求。

了解Spring Bean生命周期的内部工作原理,对于解决实际开发中遇到的问题和优化应用性能具有重要意义。希望本文的详细解析能够帮助您更深入地理解Spring框架,提升您的开发技能。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-06-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Spring之Bean的生命周期详解
    • Bean的生命周期概述
      • createBean方法详解
        • 1. resolveBeanClass方法
        • 2. prepareMethodOverrides方法
        • 3. resolveBeforeInstantiation方法
        • 4. doCreateBean方法
        • 5. registerDisposableBeanIfNecessary方法
      • 详细分析每个步骤
        • 实例化前准备
        • 实例化Bean
        • 属性填充
        • 初始化Bean
        • 销毁Bean
      • 总结
      相关产品与服务
      容器服务
      腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档