Spring之bean的生命周期

2024-06-06 08:21:31 浏览数 (2)

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框架,提升您的开发技能。

0 人点赞