Spring之Bean的生命周期详解
在Spring框架中,Bean的创建和管理是通过Spring容器来完成的。Spring Bean生命周期包括实例化、属性填充、初始化、销毁等多个步骤。本文将详细解析Spring中Bean的生命周期,并重点介绍AbstractAutowireCapableBeanFactory
类中的createBean
方法及其相关的方法调用。
Bean的生命周期概述
Spring Bean的生命周期分为多个阶段,每个阶段都由特定的方法和机制来完成:
- 实例化前准备:解析Bean定义,确定Bean类型。
- 实例化:创建Bean实例。
- 属性填充:对Bean的各个属性进行依赖注入。
- 初始化:执行自定义的初始化方法和Spring的
BeanPostProcessor
回调。 - 使用:Bean已经完全初始化并可以使用。
- 销毁:容器关闭时,对Bean进行清理工作,执行销毁方法。
下面我们将通过源码详细解析每个步骤的实现。
createBean
方法详解
createBean
方法是Spring中创建Bean实例的核心方法。该方法的实现位于AbstractAutowireCapableBeanFactory
类中:
@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
来尝试返回代理对象:
@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
方法
调用InstantiationAwareBeanPostProcessor
的postProcessBeforeInstantiation
方法:
@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
方法
调用BeanPostProcessor
的postProcessAfterInitialization
方法:
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
:
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对象:
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定义中是否包含了需要重写的方法,并进行相应的准备工作:
public void prepareMethodOverrides() throws BeanDefinitionValidationException {
if (hasMethodOverrides()) {
getMethodOverrides().getOverrides().forEach(this::prepareMethodOverride);
}
}
方法重写的准备工作包括验证方法签名和确保方法的可访问性。这一步骤对于支持方法重写功能的Bean非常重要,例如使用CGLIB动态代理的Bean。
实例化Bean
实例化Bean是通过调用createBeanInstance
方法来实现的。该方法负责根据不同的情况创建Bean实例,包括构造方法自动装配、工厂方法实例化以及默认的无参构造函数实例化。
构造方法自动装配
如果Bean定义中包含构造函数参数,或者需要进行构造函数自动装配,Spring会调用autowireConstructor
方法:
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
方法:
protected BeanWrapper instantiateUsingFactoryMethod(String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);
}
工厂方法实例化会根据Bean定义中的工厂方法名,通过反射调用工厂方法创建Bean实例。
默认无参构造函数实例化
如果Bean定义中既没有构造函数参数,也没有工厂方法,Spring会调用instantiateBean
方法:
protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
try {
Object beanInstance;
if (System.getSecurityManager() != null) {
beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
getInstantiationStrategy().instantiate(mbd, beanName, this), getAccessControlContext());
} else {
beanInstance =
getInstantiationStrategy().instantiate(mbd, beanName, this);
}
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw;
} catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
}
}
该方法会调用默认的无参构造函数创建Bean实例,并返回一个包装了Bean实例的BeanWrapper
对象。
属性填充
属性填充是通过populateBean
方法来实现的。该方法负责对Bean实例的属性进行依赖注入,包括自动装配和手动指定的属性值。
自动装配
自动装配是通过autowireByName
和autowireByType
方法来实现的。这些方法会根据Bean定义中的自动装配模式,按照名称或类型进行依赖注入。
手动指定的属性值
如果Bean定义中包含了手动指定的属性值,Spring会调用applyPropertyValues
方法将这些属性值设置到Bean实例上:
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
方法来实现的。该方法会调用一系列的回调方法,包括BeanPostProcessor
的postProcessBeforeInitialization
和postProcessAfterInitialization
方法,以及Bean实例中的初始化方法。
调用BeanPostProcessor
回调
BeanPostProcessor
回调方法用于在Bean初始化的前后执行一些自定义逻辑,例如代理对象的创建和自定义初始化逻辑的执行。
调用Bean实例的初始化方法
如果Bean实例实现了InitializingBean
接口,Spring会调用afterPropertiesSet
方法。如果Bean定义中指定了初始化方法,Spring会通过反射调用该方法:
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的作用域和生命周期,注册相应的销毁回调:
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框架,提升您的开发技能。