spring bean 生命周期

spring IOC 源码分析

Spring的单例对象的初始化主要分为三步

image.png
  1. createBeanInstance:实例化,其实也就是调用对象的构造方法实例化对象
  2. populateBean:填充属性,这一步主要是多bean的依赖属性进行填充
  3. initializeBean:调用spring xml中的init 方法。

springbean生命周期的构成

Bean的完整生命周期经历了各种方法调用,这些方法可以划分为以下几类:

  1. Bean自身的方法: 这个包括了Bean本身调用的方法和通过配置文件中<bean>的init-method和destroy-method指定的方法
  2. Bean级生命周期接口方法: 这个包括了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean这些接口的方法
  3. 容器级生命周期接口方法:这个包括了InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 这两个接口实现,一般称它们的实现类为“后处理器”。
  4. 工厂后处理器接口方法: 这个包括了AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer等等非常有用的工厂后处理器接口的方法。工厂后处理器也是容器级的。在应用上下文装配配置文件之后立即调用。

spring bean的生命周期

就是穿插在spring bean 初始化三个步骤的中间,具体的流程见下面。黄色为主线,同颜色的表示同一个对象

spring bean 生命周期

spring IOC以及bean生命周期源码分析

以下组要通过分析spring ioc源码的方式让大家理解spring bean的生命周期,源码分析过程只保留主线,一些不相关或者不重要的代码都省去。建议大家按照这个主线自已单步调试一下。

1. 加载bean配置文件

ApplicationContext factory = new ClassPathXmlApplicationContext("application-context.xml");

ClassPathXmlApplicationContext 构造函数内部主要就调用了一个方法-refresh方法。refresh方法就包含了spring ioc的全部流程。下面我们详细的分析

2. refresh()方法

public void refresh() throws BeansException, IllegalStateException {
// 设置一些环境变量、创建Environment,准备工作
    prepareRefresh();
//创建beanFactory,加载BeanDefinition带beanFactory
    ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//beanFactory设置一些必要的信息
    prepareBeanFactory(beanFactory);
    try {
        postProcessBeanFactory(beanFactory);
//调用实现了BeanFactoryPostProcessor接口的postProcessBeanFactory方法
        invokeBeanFactoryPostProcessors(beanFactory);
//注册实现BeanPostProcessor接口的bean,相当于bean的拦截器
        registerBeanPostProcessors(beanFactory);
//国际化相关处理
        initMessageSource();
//初始化容器的广播时间
        initApplicationEventMulticaster();
        onRefresh();
// 注册listeners beans
        registerListeners();
// 实例bean,bean的生命周期大部分都在这个方法中
        finishBeanFactoryInitialization(beanFactory);
// 发布finish通知, 注册bean的生命周期bean
        finishRefresh();
    } catch (BeansException ex) {
        destroyBeans();
        cancelRefresh(ex);
    }
// 清空bean定义的一些元数据信息
    resetCommonCaches();
}

2.1 prepareRefresh()方法
protected void prepareRefresh() {
/*
其实这个方法里面什么也没有做,但是可以重写改方法,设置一些环境变量。比如WebApplicationContext的实现类中AbstractRefreshableWebApplicationContext中就设置了servlet的一些初始变量
*/
    initPropertySources();
/*
验证设置的环境变量是不是正确,有没有包含空值
*/
    getEnvironment().validateRequiredProperties();
    this.earlyApplicationEvents = new LinkedHashSet<>();
}
2.2 obtainFreshBeanFactory()方法
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    refreshBeanFactory();
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    return beanFactory;
}
2.2.1 refreshBeanFactory() 方法
@Override
protected final void refreshBeanFactory() throws BeansException {
// 创建BeanFactory
    DefaultListableBeanFactory beanFactory = createBeanFactory();
    beanFactory.setSerializationId(getId());
    customizeBeanFactory(beanFactory);
// 从xml文件或者注解加载BeanDefinition,存到DefaultListableBeanFactory的beanDefinitionMap字段
    loadBeanDefinitions(beanFactory);
}
2.3 prepareBeanFactory()方法
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    //设置classLoader
    beanFactory.setBeanClassLoader(getClassLoader());
        //el表达式支持
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    // 添加BeanPostProcessor, 不知道干嘛用的
    // Configure the bean factory with context callbacks.
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    // 
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));    
//下面三个bean主要是系统的一些变量设置等等
    beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment())      
    beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties()) 
    beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
2.4 invokeBeanFactoryPostProcessors()方法
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {        
/*
这个方法里面的代码比较长,总的来说就是调用实现了BeanDefinitionRegistryPostProcessor、BeanFactoryPostProcessor接口的中的方法。在调用的时候按照接口是否实现PriorityOrdered, Ordered, 和其余的顺序调用。
1、如果需要在修改添加等对BeanDefinition的操作的话,实现BeanDefinitionRegistryPostProcessor接口
2、如果统计bean的一些信息,修改bean在配置BeanDefinition中的属性值等,实现BeanFactoryPostProcessor接口
*/ 
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
}
2.5 registerBeanPostProcessors()方法
与BeanFactoryPostProcessors类似,按一定的顺序注册实现BeanPostProcessor的接口
2.6 finishBeanFactoryInitialization()方法
// 实例化剩余的非lazy的bean,核心的代码都在这里面
beanFactory.preInstantiateSingletons()
2.6.1 preInstantiateSingletons() 方法
public void preInstantiateSingletons() throws BeansException {
    List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
    for (String beanName : beanNames) {
//如果bean有父类,那么这个bean是可以合并的,需要把父类的相关信息比如属性和子类的合并。
        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
        if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 如果是FactoryBean
            if (isFactoryBean(beanName)) {
                Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
                if (bean instanceof FactoryBean) {
                    if (isEagerInit) {
                        getBean(beanName);
                    }
                }
            }
            else {
                getBean(beanName);
            }
        }
    }

    // Trigger post-initialization callback for all applicable beans...
    for (String beanName : beanNames) {
        Object singletonInstance = getSingleton(beanName);
        if (singletonInstance instanceof SmartInitializingSingleton) {
            final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
            if (System.getSecurityManager() != null) {
                AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                    smartSingleton.afterSingletonsInstantiated();
                    return null;
                }, getAccessControlContext());
            }
            else {
                smartSingleton.afterSingletonsInstantiated();
            }
        }
    }
}
2.6.1.1 getSingleton(String beanName, ObjectFactory<?> singletonFactory)方法

preInstantiateSingletons 会调用getBean(), getBean() 会调用doGetBean(),doGetBean()会调用getSingleton(),这是一个重要的方法,需要提出分析一下

Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
        // 如果singletonObject中没有创建好bean,就调用getObject方法。singletonFactory是函数接口,对应下面的createBean方法
     singletonObject = singletonFactory.getObject();
}
addSingleton(beanName, singletonObject);
2.6.1.1.1 createBean()
createBean(){
// Give BeanPostProcessors a chance to return a proxy instead of the target 
//在bean执行构造函数之前,给最后一个机会去执行一些操作,需要bean实现InstantiationAwareBeanPostProcessorAdapter接口
    Object bean = bean instance.resolveBeforeInstantiation(beanName, mbdToUse);
//创建bean
    Object beanInstance = doCreateBean(beanName, mbdToUse, args);
}
2.6.1.1.1.1 doCreateBean()
//填充bean的属性,并且允许在设置bean属性值之前做一些操作,比如修改属性值
    populateBean(beanName, mbd, instanceWrapper);
/*
1、bean感知,调用setBeanName和setBeanFactory接口
2、执行init-method方法之前执行一些处理工作,对应的方法是postProcessBeforeInitialization
3、调用InitializingBean.afterPropertiesSet()方法
4、调用init-method方法
5、执行BeanPostProcessor的postProcessAfterInitialization方法
6、执行InstantiationAwareBeanPostProcessorAdapter的postProcessAfterInitialization方法
*/
    exposedObject = initializeBean(beanName, exposedObject, mbd);
//获取bean
    Object earlySingletonReference = getSingleton(beanName, false);
//注册bean的DisposableBean(销毁使用)
    registerDisposableBeanIfNecessary(beanName, bean, mbd);
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,193评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,306评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,130评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,110评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,118评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,085评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,007评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,844评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,283评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,508评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,667评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,395评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,985评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,630评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,797评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,653评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,553评论 2 352

推荐阅读更多精彩内容