解析Spring中Bean的生命周期

本文涉及的产品
云解析DNS,个人版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 解析Spring中Bean的生命周期

解析Spring框架中Bean的生命周期不仅可以帮助我们更好地理解Spring的工作机制,还能让我们在实际开发中更加得心应手。Spring管理Bean的生命周期涉及多个步骤,从实例化到销毁,每一个步骤都有其独特的处理逻辑。本文将通过源码详细解析Spring中Bean的生命周期。

 

1. Bean的生命周期概述

 

Spring中Bean的生命周期包括以下几个主要阶段:

 

1. **实例化(Instantiation)**:创建Bean实例。

2. **属性填充(Populate properties)**:将依赖注入到Bean实例中。

3. **初始化(Initialization)**:调用初始化方法。

4. **使用(Usage)**:Bean处于就绪状态,供应用程序使用。

5. **销毁(Destruction)**:容器关闭时调用销毁方法。

 

这些阶段由不同的组件和机制来共同完成,如`BeanFactory`,`BeanPostProcessor`,以及各种回调接口等。

 

2. 实例化Bean

 

实例化过程由`AbstractAutowireCapableBeanFactory`类的`createBeanInstance`方法负责。它根据Bean定义信息选择合适的构造函数或工厂方法来创建Bean实例。

 

```java
protected Object createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    // 如果设置了工厂方法,则通过工厂方法创建Bean
    if (mbd.getFactoryMethodName() != null) {
        return instantiateUsingFactoryMethod(beanName, mbd, args);
    }
 
    // 尝试使用默认构造函数或带参数的构造函数
    Constructor<?> constructorToUse = null;
    synchronized (mbd.constructorArgumentLock) {
        constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
        if (constructorToUse == null) {
            final Class<?> beanClass = resolveBeanClass(mbd, beanName);
            if (beanClass != null) {
                if (!Modifier.isPublic(beanClass.getModifiers())) {
                    throw new BeanCreationException(
                            beanName, "Bean class isn't public, and non-public classes not supported: " + beanClass.getName());
                }
                try {
                    constructorToUse = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
                    mbd.resolvedConstructorOrFactoryMethod = constructorToUse;
                } catch (Throwable ex) {
                    throw new BeanCreationException(beanName, "Resolution of declared constructors on bean Class [" + beanClass.getName() + "] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
                }
            }
        }
    }
    return instantiateBean(beanName, mbd, constructorToUse);
}
```

 

该方法首先检查Bean定义中是否指定了工厂方法,如果有则通过工厂方法创建Bean实例;否则,尝试使用默认构造函数或带参数的构造函数。

 

3. 属性填充

 

一旦Bean实例创建完成,Spring会将依赖注入到该实例中。这一步由`populateBean`方法负责。

 

```java
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    if (bw == null) {
        if (mbd.hasPropertyValues()) {
            throw new BeanCreationException(
                    beanName, "Cannot apply property values to null instance");
        } else {
            // Skip property population phase for an existing null instance.
            return;
        }
    }
 
    // 应用 InstantiationAwareBeanPostProcessors
    boolean continueWithPropertyPopulation = true;
 
    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessors(InstantiationAwareBeanPostProcessor.class)) {
            if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                continueWithPropertyPopulation = false;
                break;
            }
        }
    }
 
    if (!continueWithPropertyPopulation) {
        return;
    }
 
    PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
 
    if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
            mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
        MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
        if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
            autowireByName(beanName, mbd, bw, newPvs);
        }
        if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
            autowireByType(beanName, mbd, bw, newPvs);
        }
        pvs = newPvs;
    }
 
    // 应用 BeanPostProcessors 修改属性值
    boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
    boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
 
    if (hasInstAwareBpps || needsDepCheck) {
        PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
        if (hasInstAwareBpps) {
            for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessors(InstantiationAwareBeanPostProcessor.class)) {
                PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
                if (pvsToUse == null) {
                    if (pvs == null) {
                        pvs = mbd.getPropertyValues();
                    }
                    pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                    if (pvsToUse == null) {
                        return;
                    }
                }
                pvs = pvsToUse;
            }
        }
        if (needsDepCheck) {
            checkDependencies(beanName, mbd, filteredPds, pvs);
        }
    }
 
    // 将属性值应用到 Bean 实例
    if (pvs != null) {
        applyPropertyValues(beanName, mbd, bw, pvs);
    }
}
```

 

`populateBean`方法首先应用`InstantiationAwareBeanPostProcessor`接口的`postProcessAfterInstantiation`方法,对Bean实例进行后续处理,接着根据自动装配模式(byName或byType)进行依赖注入,最后将属性值应用到Bean实例。

 

4. 初始化Bean

 

在属性填充完成后,Spring会调用Bean的初始化方法,这一步由`initializeBean`方法负责。

 

```java
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
    if (System.getSecurityManager() != null) {
        AccessControlContext acc = getAccessControlContext();
        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            invokeAwareMethods(beanName, bean);
            return null;
        }, acc);
    } else {
        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;
}
```

 

`initializeBean`方法首先调用`invokeAwareMethods`方法处理实现了`Aware`接口的Bean,例如,如果Bean实现了`BeanNameAware`接口,则会调用`setBeanName`方法。接着,方法应用`BeanPostProcessor`接口的`postProcessBeforeInitialization`方法,然后调用Bean的初始化方法(如`@PostConstruct`注解的方法或自定义的初始化方法)。最后,应用`BeanPostProcessor`接口的`postProcessAfterInitialization`方法。

 

5. 销毁Bean

 

当容器关闭时,Spring会调用Bean的销毁方法,这一步由`destroyBean`方法负责。

 

```java
protected void destroyBean(String beanName, Object bean, RootBeanDefinition mbd) {
    new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessorCache().destructionAware).destroy();
}
```

 

`destroyBean`方法使用`DisposableBeanAdapter`来管理Bean的销毁过程。`DisposableBeanAdapter`会检查Bean是否实现了`DisposableBean`接口或定义了自定义的销毁方法,并调用相应的销毁方法。

 

总结

 

通过对Spring源码的详细分析,我们可以看到Spring是如何管理Bean的生命周期的:

 

1. **实例化**:通过反射机制创建Bean实例。

2. **属性填充**:将依赖对象注入到Bean实例中。

3. **初始化**:在属性填充完毕后调用初始化方法。

4. **销毁**:在容器关闭时调用销毁方法。

 

这种设计使得Spring能够灵活地管理Bean的生命周期,并提供了丰富的扩展点供开发者自定义Bean的创建和销毁逻辑。通过了解这些底层机制,我们可以更好地使用和扩展Spring框架,满足复杂应用的需求。

目录
相关文章
|
14天前
|
设计模式 监控 Java
解析Spring Cloud中的断路器模式原理
解析Spring Cloud中的断路器模式原理
|
14天前
|
安全 Java 数据安全/隐私保护
解析Spring Security中的权限控制策略
解析Spring Security中的权限控制策略
|
1天前
|
XML Java 数据格式
如果在创建Bean的过程中发生异常,Spring会如何处理
如果在创建Bean的过程中发生异常,Spring会如何处理
|
1天前
|
Java Spring 容器
在Spring中,实例化Bean是通过什么方式实现的
在Spring中,实例化Bean是通过什么方式实现的
|
14天前
|
监控 安全 Java
解析Spring Boot中的Actuator端点
解析Spring Boot中的Actuator端点
|
15天前
|
Java Spring
解析Spring Boot中的配置文件与外部化配置
解析Spring Boot中的配置文件与外部化配置
|
15天前
|
Java Spring
解析Spring Boot中的事务管理机制
解析Spring Boot中的事务管理机制
|
1月前
|
XML Java 数据格式
深度解析 Spring 源码:从 BeanDefinition 源码探索 Bean 的本质
深度解析 Spring 源码:从 BeanDefinition 源码探索 Bean 的本质
33 3
|
18天前
|
存储 安全 Java
深度长文解析SpringWebFlux响应式框架15个核心组件源码
以上是Spring WebFlux 框架核心组件的全部介绍了,希望可以帮助你全面深入的理解 WebFlux的原理,关注【威哥爱编程】,主页里可查看V哥每天更新的原创技术内容,让我们一起成长。
|
19天前
|
关系型数据库 分布式数据库 数据库
PolarDB-X源码解析:揭秘分布式事务处理
【7月更文挑战第3天】**PolarDB-X源码解析:揭秘分布式事务处理** PolarDB-X,应对大规模分布式事务挑战,基于2PC协议确保ACID特性。通过预提交和提交阶段保证原子性与一致性,使用一致性快照隔离和乐观锁减少冲突,结合故障恢复机制确保高可用。源码中的事务管理逻辑展现了优化的分布式事务处理流程,为开发者提供了洞察分布式数据库核心技术的窗口。随着开源社区的发展,更多创新实践将促进数据库技术进步。
21 3

推荐镜像

更多