Spring 源码十分庞大,创建Bean的逻辑更是错综复杂,假如对每个分支逻辑都事无巨细的研究分析,可能会陷入到 Spring 那庞大的逻辑沼泽中。因此我们仅需要将关注重心放在核心流程上,对于那些旁枝末叶点到即止。对主要的脉络关系进行梳理,建立一个清晰的印象。
我们在使用Spring框架开发过程中,通过一些简单的注解或方法便可实现 bean 的创建与获取,这就是Spring IOC容器的魅力。
而 Bean 的生命周期管理则是 Spring 实现 IOC 容器中比较重要的能力,了解 Bean 的生命周期可以帮助我们在开发过程中避免不必要的问题或者实现针对性的功能扩展,提高开发效率。本文将结合源码介绍一个普通 Bean 的一生。
Bean 的诞生
进入Spring 内部首先需要找到一扇门,而这扇门下就隐藏着一个复杂的世界。首先创建一个简单的Spring boot 项目并写下以下代码
java
代码解读
复制代码
@Configuration public class BeanConfig { @Bean(name = "withelios") public SimpleBean simpleBean(){ return new SimpleBean(1, "withelios"); } }
通过一个main 方法获取名为withelios
的 bean 实例
java
代码解读
复制代码
public static void main(String[] args) { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfig.class); SimpleBean bean = (SimpleBean) applicationContext.getBean("withelios"); System.out.println(bean); }
AnnotationConfigApplicationContext 是一个独立的ApplicationContext 实现类,它支持对@Configuration @Component等注解类的扫描与注册,同时支持包的扫描.
代码中applicationContext.getBean("withelios")
是如何完成 Bean 的创建的? 下面跟着源码打开门后的秘密
getBean
查看源码getBean
方法发现其实是直接调用 DefaultListableBeanFactory#getBean
方法,最终通过执行抽象父类 AbstractBeanFactory#doGetBean
方法去获取bean 实例。而我们一直所指的IOC容器也就是指 BeanFactory 的系列接口与相关实现功能。
查看源码
java
代码解读
复制代码
protected <T> T doGetBean( String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException { // bean 名称转换,通过别名获取规范名称 // 删除 FactoryBean bean 名称 '&' 前缀 String beanName = transformedBeanName(name); Object beanInstance; // 检查单例池中是否已存在,可获取提前暴露的实例(循环引用) Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { // 假如为FactoryBean类型,则通过 getObject 方法获取其真实类型 beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { // 检查原型实例是否已经在创建 if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } // 假如bean definition 在父容器中,从父容器中获取实例 BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { ... } if (!typeCheckOnly) { markBeanAsCreated(beanName); } try { // 获取BeanDefinition RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); // 保证优先初始化当前实例通过 dependsOn 指定的依赖实例 String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dep : dependsOn) { // 禁止循环指定 dependsOn if (isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } // 缓存依赖关系 registerDependentBean(dep, beanName); try { // 优先创建依赖实例 getBean(dep); } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex); } } } // 创建单例bean if (mbd.isSingleton()) { // 调用ObjectFactory匿名类getObject方法创建实例,并缓存在单例池中 sharedInstance = getSingleton(beanName, () -> { try { // 创建bean实例,抽象模板方法 return createBean(beanName, mbd, args); } catch (BeansException ex) { // 销毁 bean 实例 destroySingleton(beanName); throw ex; } }); // 假如为FactoryBean类型,则通过 getObject 方法获取其真实类型 beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } // 原型实例 else if (mbd.isPrototype()) {...} // 其他作用域实例 else {...} } catch (BeansException ex) { ... } finally { beanCreation.end(); } } // 根据类型进行适配转换 return adaptBeanInstance(name, beanInstance, requiredType); }
FactoryBean 是创建Bean的工厂Bean,而BeanFactory 是Bean的容器,两者有本质上的区别。FactoryBean主要用于那些创建过程需要复杂的配置属性或者涉及其他组件bean构建的实例bean
简要概述下doGetBean
方法核心逻辑
- 首先检查单例池是否已经缓存实例
- 假如存在父容器并且bean definition 存在于父容器中,从父容器中获取实例
- 优先初始化当前实例指定的依赖实例
- 创建实例并缓存到单例池中
- 根据指定类型进行适配转换
创建 bean 的核心方法是getSingleton
方法,方法入参是beanName
和一个 ObjectFactory
实例,这里采用了匿名类的方式。
java
代码解读
复制代码
sharedInstance = getSingleton(beanName, () -> { try { // 创建bean实例,抽象模板方法 return createBean(beanName, mbd, args); } catch (BeansException ex) { // 销毁 bean 实例 destroySingleton(beanName); throw ex; } });
该方法是父类 DefaultSingletonBeanRegistry
提供,以下是代码逻辑
java
代码解读
复制代码
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { synchronized (this.singletonObjects) { Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { boolean newSingleton = false; try { // 调用 ObjectFactory 的方法获取实例 // 最终调用的是 createBean 方法 singletonObject = singletonFactory.getObject(); newSingleton = true; } ... if (newSingleton) { // 添加到单例池中 addSingleton(beanName, singletonObject); } } return singletonObject; } }
该方法逻辑就是判断单例池中是否已存在指定bean ,假如不存在则执行传入 ObjectFactory实例的 getObject 的方法,并将其放置到单例池中,否则直接返回。
所以上述代码会执行 createBean
方法创建实例,createBean
为AbstractBeanFactory定义的抽象模板方法,AbstractAutowireCapableBeanFactory
最终实现了该方法。
createBean
查看方法代码
java
代码解读
复制代码
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { RootBeanDefinition mbdToUse = mbd; // 确保创建bean 之前,bean 的类已经加载解析完成 Class<?> resolvedClass = resolveBeanClass(mbd, beanName); if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { mbdToUse = new RootBeanDefinition(mbd); mbdToUse.setBeanClass(resolvedClass); } ... try { // InstantiationAwareBeanPostProcessor 的实例化前扩展点 // 可以在该扩展点将代理对象替换目标实例 Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null) { return bean; } } ... try { // 创建实例 Object beanInstance = doCreateBean(beanName, mbdToUse, args); return beanInstance; } ... }
上述代码存在一个比较特殊的代码逻辑 resolveBeforeInstantiation
。该方法主要是Spring 在bean 实例化前提供的扩展点,主要是通过执行 InstantiationAwareBeanPostProcessor 扩展方法实现。通过实现该接口方法在 bean 实例化前进行功能扩展,比如使用代理对象替换目标对象,从而实现特定的业务逻辑。
接着进入 doCreateBean 方法
java
代码解读
复制代码
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) { // 选择合适的构造器创建实例,返回 BeanWrapper 包装类 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 { // 扩展点:应用 MergedBeanDefinitionPostProcessor 扩展方法 // 允许实现修改 bean 的定义信息或缓存 bean 的元信息在扩展点使用 applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } catch (Throwable ex) {...} mbd.postProcessed = true; } } // 循环依赖 提前暴露对象实例 boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { //添加到单例工厂bean 缓存中 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } // 初始化 bean 实例 Object exposedObject = bean; try { // 填充 bean 实例属性 populateBean(beanName, mbd, instanceWrapper); //执行bean的初始化方法 exposedObject = initializeBean(beanName, exposedObject, mbd); } catch (Throwable ex) {...} // 检查循环依赖后实例改变场景问题 if (earlySingletonExposure) { ... } try { // 实例存在销毁方法则注册回调 registerDisposableBeanIfNecessary(beanName, bean, mbd); } catch (BeanDefinitionValidationException ex) {...} return exposedObject; }
BeanWrapper :Spring 为Bean实例提供的包装类,它实现了对Java bean的分析操作能力,诸如属性设置修改,获取属性类型信息等
循环依赖指单例bean间存在循环引用,比如 A 依赖于 B ,同时 B 又依赖于 A 。Spring 主要通过多级缓存实现,即在实例化A的过程中首先放置到半成品缓存中,在填充属性阶段发现依赖于B ,然后去创建实例B,在B的创建过程中发现依赖于A,则可以直接从半成品缓存获取A,完成B的创建后再去继续A的创建过程。
doCreate 方法是bean创建过程的核心方法,主要的核心逻辑:
- createBeanInstance 通过选择合适的构造方法创建实例
- applyMergedBeanDefinitionPostProcessors 执行bean定义信息的前置扩展点,通过实现
MergedBeanDefinitionPostProcessor
接口对beanDefinition 操作,比如缓存bean 元信息,或者修改相关bean 定义信息 - addSingletonFactory 为了解决循环依赖,将 bean 先放到半成品缓存中延迟初始化(Spring的循环依赖问题较为复杂,本文主要解析Bean的创建过程)
- populateBean 填充bean 的属性信息,实现依赖注入
- initializeBean 执行初始化方法
- registerDisposableBeanIfNecessary 注册 bean 的销毁方法
createBeanInstance
java
代码解读
复制代码
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) { // 确保 bean class 已正确加载 Class<?> beanClass = resolveBeanClass(mbd, beanName); // 存在指定的 Supplier 实例对象则直接通过 Supplier 获取实例bean Supplier<?> instanceSupplier = mbd.getInstanceSupplier(); if (instanceSupplier != null) { return obtainFromSupplier(instanceSupplier, beanName); } // 存在指定的工厂方法则直接通过工厂方法获取实例 bean if (mbd.getFactoryMethodName() != null) { return instantiateUsingFactoryMethod(beanName, mbd, args); } // 如果存在解析过的实例构造方法则直接使用 boolean resolved = false; boolean autowireNecessary = false; if (args == null) { synchronized (mbd.constructorArgumentLock) { if (mbd.resolvedConstructorOrFactoryMethod != null) { resolved = true; autowireNecessary = mbd.constructorArgumentsResolved; } } } if (resolved) { if (autowireNecessary) { return autowireConstructor(beanName, mbd, null, null); } else { return instantiateBean(beanName, mbd); } } // 通过 SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors 方法确定构造方法 Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { return autowireConstructor(beanName, mbd, ctors, args); } // 指定的构造器方法 ctors = mbd.getPreferredConstructors(); if (ctors != null) { return autowireConstructor(beanName, mbd, ctors, null); } // 使用默认构造器 return instantiateBean(beanName, mbd); }
SmartInstantiationAwareBeanPostProcessor 是Spring 框架在 BeanPostProcessor 基础上提供的内部扩展接口,主要提供类型推断、构造器候选与提前暴露引用(解决循环依赖问题)等能力
该方法的主要目标就是实例化bean 的方式并完成实例化,实例化优先级如下
- bean 定义指定的 Supplier 实例化
- bean 定义指定的 FactoryMethod 实例化
- 使用解析过的构造器初始化
- SmartInstantiationAwareBeanPostProcessor 扩展候选构造方法
- bean 定义指定的优先构造器
- 使用默认构造器
populateBean
该方法主要逻辑是完成实例属性的注入,通过 Spring 容器完成控制翻转。比如 添加了 @Autowired``@Value
注解的成员变量可以
java
代码解读
复制代码
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { // 扩展点:InstantiationAwareBeanPostProcessors#postProcessAfterInstantiation // 可以在该扩展点实现定制化的注入方式 if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) { if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { return; } } } PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); // 根据Bean配置的指定依赖注入方式完成注入,默认是0,即不走以下逻辑 // @Bean(autowire = Autowire.BY_NAME) 可指定注入类型(已废弃) int resolvedAutowireMode = mbd.getResolvedAutowireMode(); if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // 根据名称注入属性 if (resolvedAutowireMode == AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // 根据类型注入属性 if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } // 检查是否存在 InstantiationAwareBeanPostProcessor boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); PropertyDescriptor[] filteredPds = null; if (hasInstAwareBpps) { if (pvs == null) { pvs = mbd.getPropertyValues(); } for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) { // 扩展点:InstantiationAwareBeanPostProcessor#postProcessProperties // 比如 AutowiredAnnotationBeanPostProcessor 实现类支持了 Autowired 和 Value注解 PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } // 扩展点:InstantiationAwareBeanPostProcessors#postProcessPropertyValues (标记废弃) pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { return; } } pvs = pvsToUse; } } if (needsDepCheck) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } // 校验依赖属性 checkDependencies(beanName, mbd, filteredPds, pvs); } if (pvs != null) { //注入属性 applyPropertyValues(beanName, mbd, bw, pvs); } }
该方法的作用就是填充实例属性,比如通过名称或者类型进行注入,执行InstantiationAwareBeanPostProcessors
的 postProcessAfterInstantiation
与 postProcessProperties
回调方法。
initializeBean
该方法主要是执行相关的初始化方法,并执行 Spring 的 bean 初始化扩展点
java
代码解读
复制代码
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) { ... // 扩展点:Aware接口回调 // 1.BeanNameAware#setBeanName 设置 beanName // 2.BeanClassLoaderAware#setBeanClassLoader 设置 classLoader // 3.BeanFactory#setBeanFactory 设置 BeanFactory invokeAwareMethods(beanName, bean); ... Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { // 扩展点:BeanPostProcessor#postProcessBeforeInitialization wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { // 扩展点:初始化回调 // 1.InitializingBean#afterPropertiesSet // 2.定制化 init-method 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()) { // 扩展点:BeanPostProcessor#postProcessAfterInitialization wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }
初始化方法的核心的代码逻辑如下
- invokeAwareMethods 执行实现 Aware 接口的实例的回调
- BeanNameAware#setBeanName 设置 beanName
- BeanClassLoaderAware#setBeanClassLoader 设置 classLoader
- BeanFactory#setBeanFactory 设置 BeanFactory
- applyBeanPostProcessorsBeforeInitialization 执行 BeanPostProcessor 的初始化前置回调方法
- invokeInitMethods 执行初始化方法的回调
- 假如当前实例为 InitializingBean 实现类则执行 afterPropertiesSet 回调方法
- 执行自定义初始化方法,例如
@Bean(initMethod = "init")
注解执行初始化方法
- applyBeanPostProcessorsAfterInitialization 执行 BeanPostProcessor 的初始化后置回调方法
查看源码会发现 Spring 针对 Bean 的初始化过程添加了丰富的扩展点,开发人员可通过这些扩展点实现定制化的功能和需求,这些扩展点也是 Spring 框架灵活性的体现。
registerDisposableBeanIfNecessary
该方法主要是判断实例 Bean 是否允许被销毁,然后进行注册缓存。在 Spring 容器销毁阶段时执行这些 Bean 销毁回调,实现 Bean 实例的最终阶段的逻辑操作,比如资源回收、线程池销毁等。
java
代码解读
复制代码
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()) { //将实例通过 DisposableBeanAdapter 包装类缓存起来 registerDisposableBean(beanName, new DisposableBeanAdapter( bean, beanName, mbd, getBeanPostProcessorCache().destructionAware, acc)); } else { // 自定义作用域的销毁 ... } } }
假如当前 Bean 允许被销毁则通过 DisposableBeanAdapter
包装类放置到缓存中,通过适配器模式封装了实例销毁的具体细节处理,容器在实例需要销毁时执行包装类的 destroy 方法完成销毁操作。
到此为止一个 Bean 就被完整创建出来并可以被使用。而 Bean 的生命周期并没有结束,最终的销毁处理同样充满细节。下面跟随源码查看下 Bean 的消亡之路。
Bean 的消亡
DisposableBeanAdapter
通过上文源码解析知晓, Spring 在 Bean 创建完成后会注册 bean 实例的销毁回调,而这个回调主要由 DisposableBeanAdapter 实现。通过该类名可以猜测出其使用了装饰器模式,主要为了适配各种不同销毁方式,比如 DisposableBean 接口实现,自定义销毁方法,AutoCloseable 接口实现等。
DisposableBeanAdapter
构造方法会针对 Bean 的销毁方法进行解析并缓存。
java
代码解读
复制代码
public DisposableBeanAdapter(Object bean, String beanName, RootBeanDefinition beanDefinition, List<DestructionAwareBeanPostProcessor> postProcessors, @Nullable AccessControlContext acc) { ... // 判断是否为 DisposableBean 接口实现 this.invokeDisposableBean = (this.bean instanceof DisposableBean && !beanDefinition.isExternallyManagedDestroyMethod("destroy")); ... // 推断Bean的销毁方法 String destroyMethodName = inferDestroyMethodIfNecessary(bean, beanDefinition); if (destroyMethodName != null && !(this.invokeDisposableBean && "destroy".equals(destroyMethodName)) && !beanDefinition.isExternallyManagedDestroyMethod(destroyMethodName)) { this.destroyMethodName = destroyMethodName; // 获取销毁方法 Method destroyMethod = determineDestroyMethod(destroyMethodName); ... this.destroyMethod = destroyMethod; } //筛选获取可以应用在当前实例上的 DestructionAwareBeanPostProcessor this.beanPostProcessors = filterPostProcessors(postProcessors, bean); }
DestructionAwareBeanPostProcessor 是 BeanPostProcessor 子接口,主要是针对 Bean 在销毁前添加的扩展点
构造方法主要的逻辑是获取真正的销毁方法,并筛选出可执行的销毁前置处理器
- 判断 Bean 是否为 DisposableBean 实现
- 推断出 bean 实例的销毁方法,推断顺序如下
- Bean 定义指定的销毁方法,比如
@Bean(destroyMethod = "end")
方式 - AutoCloseable 实现类则依次查找是否存在 close 和 shutdown 方法
- Bean 定义指定的销毁方法,比如
- 筛选出可以应用在当前实例的 DestructionAwareBeanPostProcessor
解构出与销毁相关的信息是为了真正执行销毁方式做铺垫,下面看下真正销毁时如何处理的。
destroy
Spring 在容器销毁或者 实例销毁阶段会执行相应的DisposableBeanAdapte
销毁方法 destroy。
java
代码解读
复制代码
public void destroy() { if (!CollectionUtils.isEmpty(this.beanPostProcessors)) { // DestructionAwareBeanPostProcessor 的销毁前置扩展点 for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) { processor.postProcessBeforeDestruction(this.bean, this.beanName); } } if (this.invokeDisposableBean) { try { ... // 执行 DisposableBean 接口回调 ((DisposableBean) this.bean).destroy(); ... } catch (Throwable ex) { } } // 存在销毁方法则执行否则根据销毁方法名确定销毁方法执行 if (this.destroyMethod != null) { invokeCustomDestroyMethod(this.destroyMethod); } else if (this.destroyMethodName != null) { Method methodToInvoke = determineDestroyMethod(this.destroyMethodName); if (methodToInvoke != null) { invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke)); } } }
方法内部依次会执行下面逻辑
- DestructionAwareBeanPostProcessor 前置销毁处理
- DisposableBean 的销毁回调
- 自定义销毁方法
完成上述的步骤后,最终销毁结束了自己的一生。
生命周期与扩展点
通过查看源码可以分析 Spring 将 Bean 的生命周期主要划分为
- createBeanInstance 实例化
- populateBean 属性填充
- initializeBean 初始化
- destroy 销毁
而为了提高灵活性与扩展性,Spring 针对 Bean 的每个生命阶段,有分别提供了不同的扩展点,可以通过这些扩展点实现不同的功能。
图中列出了 bean 的生命周期扩展,在不同的生命阶段 Spring 为开发人员预留了扩展接口,这也是 Spring 框架灵活性的体现,开发可以根据自己的需求实现不同的扩展接口从而完成功能增强。