首页 > 其他分享 >SpringBean生命周期

SpringBean生命周期

时间:2023-10-11 19:23:36浏览次数:37  
标签:instanceof 初始化 生命周期 mbd beanName SpringBean bean 实例

SpringBean生命周期

读源码小方法:先把所有代码块折叠,看整体,再逐步进入局部,忽略异常处理。写简单程序打断点调试。

本文主要ref

结论

  • 生命周期主要的扩展点:实例化(doGetBean()->createBeanInstance()),注入(populate),初始化(initializeBean),销毁。一般processor都是在这些点前后扩展。
  • 初始化容器的时候会把实现了BeanFactoryPostProcessor BeanPostProcessor等接口的bean实例化(不管有没有设置lazy-init),前者会在BeanDefinition加载完成后被调用,用于编辑BeanDefinition。后者的方法会在后续每一个bean的实例化前后被调用,而其子接口InstantiationAwareBeanPostProcessor的方法会在初始化前后和设置注入属性前被调用。
  • 命名中有Aware的接口比如:BeanFactoryAware,BeanNameAware用于bean在创建过程注入对应的容器资源,每个bean的这些方法只会在自己创建的时候被调用
  • 配置的init-method destory-method也只会在自己创建的时候被调用。DisposableBean,InitializingBean也是。
  • 以上并没有说明他们的顺序,顺序如下图,但实际上在一个bean创建过程中不一定所有方法都会执行。后面的代码分析中会仔细分析。
  • 分析生命周期还得结合实际用途,不然会很疑惑他们有什么用,一般和AOP之类的有关,后面再分析

20210710134349143

代码&&分析

下面将从几个扩展点介绍相应的Procesor,并且说明他们返回值对后面流程的影响及其原因(结论+代码分析)。

其实很多类、接口、方法写了详细的说明和注释,表明有什么作用。

初始化容器阶段

AbstractApplicationContext#refresh()中,以下三个函数

第一个函数本类没有实现,让子类自由发挥,比如加一些BeanPostProcessors 。但是子类似乎也没实现

This template method allows for registering special BeanPostProcessors etc in certain AbstractApplicationContext subclasses.

这里是提供给子类的扩展点,到这里的时候,所有的 Bean 都加载、注册完成了,但是都还没有初始化具体的子类可以在这步的时候添加一些特殊的 BeanFactoryPostProcessor 的实现类或做点什么事。ref

第二个注册,实例化,并且调用BeanFactoryPostProcessor 实现类的方法

Instantiate and invoke all registered BeanFactoryPostProcessor beans, respecting explicit order if given.

第三个注册和实例化BeanPostProcess

Instantiate and register all BeanPostProcessor beans, respecting explicit order if given

// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);

注意补充

ref

后来才发现在上面三个函数上面还有一个函数调用

prepareBeanFactory(beanFactory);

这个是提前注册了一些BeanPostProcessor在里面,比如ApplicationContextAwareProcessor,他的功能主要是给这些接口注入application的一些信息,他会在postProcessBeforeInitialization函数中调用这个函数。

private void invokeAwareInterfaces(Object bean) {
    if (bean instanceof EnvironmentAware) {
        ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
    }
    if (bean instanceof EmbeddedValueResolverAware) //后续省略
    if (bean instanceof ResourceLoaderAware)
    if (bean instanceof ApplicationEventPublisherAware)
    if (bean instanceof MessageSourceAware)
    if (bean instanceof ApplicationStartupAware)
    if (bean instanceof ApplicationContextAware)
}

类似的提前注入的BeanPostProcessor还有

beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));

Bean生命周期

总体逻辑图

先给流程,后面的分析就是贴代码说原因。

其实xx前xx后不一定就紧跟着xx,比如实例化后的执行实际不是紧跟着实例化,而是在注入之前。

BeanLifeCycle

实例化

入口是AbstractAutowireCapableBeanFactory#createBean(),内部关键函数调用resolveBeforeInstantiation() doCreateBean(),这两个都有实例化功能。其中doGetBean内部进一步执行后面两个阶段(注入,初始化)的函数。

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
    Object bean = null;
    if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
        // Make sure bean class is actually resolved at this point.
        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;
}

出来之后,如果返回就没有后面的doGetBean()

Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
    return bean;
}

注入属性

AbstractAutowireCapableBeanFactory#populateBean()

实例化后

if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
    for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
        // 实例化后的返回值影响是否依赖注入
        if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
            return;
        }
    }
}

注入属性前

for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
    //***************处理属性
    PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
    if (pvsToUse == null) {
        if (filteredPds == null) {
            filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
        }
        //*****************处理属性值**********返回值影响是否进行依赖注入
        pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
        if (pvsToUse == null) {
            return;
        }
    }
    pvs = pvsToUse;
}

初始化

AbstractAutowireCapableBeanFactory#initializeBean()

// 省略次要代码
// 调用Aware接口的代码,注意
invokeAwareMethods(beanName, bean);
// InitializingBean#afterProperties 和 Init-method
invokeInitMethods(beanName, wrappedBean, mbd);
//...
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
//...
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

这几行代码中的逻辑都不影响后续执行,其中,第一个内部是这样:

// 省略次要代码
if (bean instanceof Aware) {
    if (bean instanceof BeanNameAware)//....
    if (bean instanceof BeanClassLoaderAware) 
    if (bean instanceof BeanFactoryAware)
}

注意,上面 [初始化容器阶段的注意补充](# 初始化容器阶段) 中讲了,有些Aware接口的方法是在ApplicationContextAwareProcessorpostProcessBeforeInitialization, 初始化前的方法中调用的。也就是说这些Aware是在上述四行代码中的第三行中调用的。

第二个内部是这样

// InitializingBean接口
((InitializingBean) bean).afterPropertiesSet();

// 如果配置的initMethod和上面那个名字不一样就执行initMethod
if (StringUtils.hasLength(initMethodName) &&
        !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
        !mbd.hasAnyExternallyManagedInitMethod(initMethodName)) {
    invokeCustomInitMethod(beanName, bean, mbd);
}

后面两个就是遍历执行processor的方法了没什么好说的。

注册为DisposableBean

AbstractAutowireCapableBeanFactory#registerDisposableBeanIfNecessary()

无processor调用,如果实现了DisposableBean()会注册进去。他的destory()在配置的destory-method方法之前执行,和初始化那个顺序一样。

常用生命周期接口

从上面的分析也能看出来有哪些了。

只调用一次的,用于编辑Factory中的BeanDefinition

BeanFactoryPostProcessor()

在每个Bean的生命周期中调用

BeanPostProcessor && InstantiationAwareBeanPostProcessor

后者继承前者,前者只有实例化前后的两个方法,后者多了初始化前后和设置属性值之前的两个方法,一共多了四个

Aware类

有两类,上面也说了。一般这种接口要获取的东西在名字已经体现得很好了。

第一类:BeanNameAware, BeanClassLoader

第二类:EnvironmentAware, ApplicationContextAware

初始化和销毁

InitializingBean && DisposableBean

配置的初始方法和销毁方法

就是init-method destory-method,注意如果这两个方法和上一种接口的方法是重复的,那么这个不会执行。

实际用途

不同的地方有很多不同的扩展,给用户很大操作空间。据说AOP和BeanPostProcessor有很大关系,等到分析AOP原理的时候在讨论这个。

标签:instanceof,初始化,生命周期,mbd,beanName,SpringBean,bean,实例
From: https://www.cnblogs.com/BayMax0-0/p/17757957.html

相关文章

  • Vue 生命周期
    Vue生命周期Vue生命周期指的是Vue实例从创建到销毁整个过程Vue生命周期函数Vue生命周期函数(或生命周期回调函数、生命周期钩子)指的是在Vue生命周期的特定关键时间点被Vue自动调用的一些特殊函数注意事项生命周期函数的名字不可更改,但函数的具体内容是程序员根据需......
  • 生命周期
    这个是构建插件 ......
  • .NET6 startup.cs 注入 本地缓存,AddTransient ,AddScoped ,AddSingleton生命周期
    .NET6startup.cs注入本地缓存//使用缓存usingMicrosoft.Extensions.Caching.Memory;services.AddMemoryCache();//自定义缓存类,类继承接口services.AddScoped<IMemoryCacheHelper,MemoryCacheHelper>();service.cs里使用构造函数注入生成对象方法里调用对象的写,获取......
  • Vue的生命周期、钩子函数
    Vue的生命周期:一个Vue实例从创建到销毁的整个过程生命周期四个阶段:创建、挂载、更新、销毁①创建阶段:初始化工作,进行数据的响应式处理,把普通数据变成响应式数据(数据变,视图跟着变)②挂载阶段:渲染模板。结合数据与模板进行渲染③更新阶段:用户可以通过页面上的按钮等修改数......
  • 创建vue3项目、setup函数、ref函数、reactive函数、计算监听属性、生命周期、torefs、
    创建vue3项目#两种方式-vue-cli:vue脚手架---》创建vue项目---》构建vue项目--》工具链跟之前一样-vite:https://cn.vitejs.dev/-npmcreatevue@latest一路选择即可#运行vue3项目-vue-cli跟之前一样-vi......
  • Servlet 以及它的生命周期
    Servlet是Java中用于处理Web请求和生成Web响应的服务器端组件。它是JavaServletAPI的一部分,通过继承javax.servlet.Servlet接口或javax.servlet.http.HttpServlet类来实现。Servlet的生命周期包括以下几个阶段:1.初始化(Initialization):在Servlet被实例化之后,会调用其init()方法......
  • Spring的Bean生命周期
     1.实例Bean:容器寻找Bean的定义信息并将其实例化,通过doCreateBean()方法实现。protectedObjectdoCreateBean(finalStringbeanName,finalRootBeanDefinitionmbd,final@NullableObject[]args) 2.Bean属性注入:使用依赖注入,Spring按照Bean定义信息配置Bean所有......
  • Servlet的生命周期
    一、什么是Servlet?Servlet(ServerApplet)是JavaServlet的简称,称为小服务程序或服务连接器,用Java编写的服务器端程序,具有独立于平台和协议的特性,主要功能在于交互式地浏览和生成数据,生成动态Web内容。狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Se......
  • 软件工程的生命周期和模型种类
    同任何事物一样,一个软件产品或软件系统也要经历孕育、诞生、成长、成熟、衰亡等阶段,一般称为软件生命周期。根据GB8566-88(《软件工程国家标准——计算机软件开发规范》),可以将软件生命周期概括为6个阶段:可行性研究、需求分析、设计、实现、测试和维护。1、可行性研究阶段此阶段......
  • Vue源码学习(八):生命周期调用
    好家伙, Vue源码学习(七):合并生命周期(混入Vue.Mixin)书接上回,在上一篇中,我们已经实现了合并生命周期现在,我们要在我们的初始化过程中,注册生命周期 1.项目目录 红框为本篇涉及到的.js文件 2.先来看/utils/index.jsexportconstHOOKS=["beforeCreated......