SpringBean的生命周期过程

SpringBean的生命周期过程

Spring的Bean分为单例Bean(默认形式),多例Bean,以及懒加载的Bean,后两种Bean是在获取Bean对象的时候进行初始化,以下我总结的是Spring单例Bean的生命周期过程
首先我们需要知道两个概念:
1、spring bean——受spring容器管理的对象,可能经过了完整的spring bean生命周期(为什么是可能?难道还有bean是没有经过bean生命周期的?答案是有的,具体我们后面文章分析),最终存在spring容器(即spring单例池)当中;一个bean一定是个对象
2、对象——任何符合java语法规则实例化出来的对象,但是一个对象并不一定是spring bean;
其中SpringBean的生命周期,我们从两个层面分别来看待,第一个是源码层面,第二个是方法层面;

源码层面的SpringBean的生命周期过程

  • 1:实例化一个ApplicationContext的对象;
  • 2:调用bean工厂后置处理器完成扫描;
  • 3:循环解析扫描出来的类信息;
  • 4:实例化一个BeanDefinition对象来存储解析出来的信息;
  • 5:把实例化好的beanDefinition对象put到beanDefinitionMap当中缓存起来,以便后面实例化bean;
  • 6:再次调用bean工厂后置处理器;
  • 7:当然spring还会干很多事情,比如国际化,比如注册BeanPostProcessor等等,如果我们只关心如何实例化一个bean的话那么这一步就是spring调用finishBeanFactoryInitialization方法来实例化单例的bean,实例化之前spring要做验证,需要遍历所有扫描出来的类,依次判断这个bean是否Lazy,是否prototype,是否abstract等等;
  • 8:如果验证完成spring在实例化一个bean之前需要推断构造方法,因为spring实例化对象是通过构造方法反射,故而需要知道用哪个构造方法;
  • 9:推断完构造方法之后spring调用构造方法反射实例化一个对象;注意我这里说的是对象、对象、对象 ! ! !这个时候对象已经实例化出来了,但是并不是一个完整的bean,最简单的体现是这个时候实例化出来的对象属性是没有注入,所以不是一个完整的bean;
  • 10:spring处理合并后的beanDefinition
  • 11:判断是否支持循环依赖,如果支持则提前把一个工厂存入singletonFactories——map(这里我们定义为三级缓存);
  • 12:判断是否需要完成属性注入
  • 13:如果需要完成属性注入,则开始注入属性【属性注入】
  • 14:判断bean的类型回调Aware接口
  • 15:调用生命周期回调方法【初始化方法init-method】
  • 16:如果需要代理则完成代理
  • 17:put到单例池——bean完成——存在spring容器当中
    此时我们通过下面这段代码,debug走一遍X类的生命周期:
@Component
public class X  {
	//构造方法
	public X(){
		System.out.println("X create");
	}
	//生命周期初始化回调方法
	@PostConstruct
	public void zinit(){
		System.out.println("call z lifecycle init callback");
	}
}

第1步 : 实例化一个ApplicationContext的对象

在这里插入图片描述

第2步,第3步,第4步,第5步 : 调用bean工厂后置处理器完成扫描,解析类成BeanDefinition对象,并且put到beanDefinitionMap当中

其中,执行InvokeBeanDefinitionRegisterPostProcessors解析为BeanDefinition对象,并放置在beanDefinitionMap
在这里插入图片描述

第6步 : 再次执行Bean工厂后置处理器完成Cglib代理【此时是BeanFactoryPostProcessor】

那么,我们的Spring是在何时进行实例化bean?

在AbstractApplicationContext中的finishBeanFactoryInitialization(beanFactory)方法中进行实例化bean的
在这里插入图片描述

第7步 : spring调用finishBeanFactoryInitialization方法来实例化单例的bean,实例化之前spring要做验证,需要遍历所有扫描出来的类,依次判断这个bean是否Lazy,是否prototype,是否abstract等等

在这里插入图片描述
这里,我们对第七步进行简单的分析一下:

第7步详解: 单例Bean的初始化过程(基于源码)—finishBeanFactoryInitialization(beanFactory)—preInstantiateSingletons()—getBean(beanName)

这里主要针对refresh()方法中的**finishBeanFactoryInitialization(beanFactory)**进行讲解,在这个方法中完成了所有单例Bean的实例化 :

而在finishBeanFactoryInitialization(beanFactory)方法内部,实现单例bean实例化的最重要的方法为preInstantiateSingletons()方法

在这里插入图片描述
其中该preInstantiateSingletons()方法是一个beanFactory下的一个接口方法,我们在它的实现类DefaultListableBeanFactory中进行了实现
在这里插入图片描述
其中,getBean(beanName)方法是抽象类
AbstractBeanFactory
的一个空方法,里面调用了doGetBean方法

我们进入这个doGetBean方法看看:
在这里插入图片描述
进入doGetBean()方法内部,我们就可以看到其中一个方法 getSingleton(beanName) :

//先从单例池中获取缓存中保存的单实例Bean。如果能获取到说明这个Bean之前被创建过(所有创建过的单实例Bean都会被缓存起来)
Object sharedInstance = getSingleton(beanName);

在这里插入图片描述
其中,getSingleton(beanName)方法的内部实现为:

public Object getSingleton(String beanName) {
    return getSingleton(beanName, true);
}

@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    //首先会去我们的spring单例池中获取我们的beanName的bean实例是否存在 ?
    Object singletonObject = this.singletonObjects.get(beanName);
    
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        synchronized (this.singletonObjects) {
            //首先去二级缓存中找
            singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {
                //如果在我们的单例池和二级缓存均未能获取到我们的bean实例,会去三级缓存中,即singletonFactories中查找是否存在该对象
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    //如果找到了该beanName的对象(此对象没有完成Bean的生命周期...)
                    singletonObject = singletonFactory.getObject();  //返回工厂对象,即半成品对象
                    this.earlySingletonObjects.put(beanName, singletonObject);//放到二级缓存中
                    this.singletonFactories.remove(beanName);//同时将其从singletonFactories中移除掉...
                }
            }
        }
    }
    return singletonObject;
}

如果getSingleton(beanName)获取不到我们的bean实例,就会使用createBean()方法进行单例bean的创建过程,同样是在doGetBean()方法内部的
在这里插入图片描述
其中,createBean方法的内部实现为:

@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
    throws BeanCreationException {

    if (logger.isDebugEnabled()) {
        logger.debug("Creating instance of bean '" + beanName + "'");
    }
    RootBeanDefinition mbdToUse = mbd;

    // Make sure bean class is actually resolved at this point, and
    // clone the bean definition in case of a dynamically resolved Class
    // which cannot be stored in the shared merged bean definition.
    //通过RootBeanDefinition和beanName获取该bean实例的class类信息
    Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
    if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
        mbdToUse = new RootBeanDefinition(mbd);
        mbdToUse.setBeanClass(resolvedClass);
    }

    // Prepare method overrides.
    try {
        mbdToUse.prepareMethodOverrides();
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                                               beanName, "Validation of method overrides failed", ex);
    }

    try {
        // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
        //让BeanPostProcessors拦截返回代理对象---InstantiationAwareBeanPostProcessors提前执行
        //第一次调用后置处理器
        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 {
        //使用doCreateBean创建bean(重点...)
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
        if (logger.isDebugEnabled()) {
            logger.debug("Finished creating instance of bean '" + beanName + "'");
        }
        return beanInstance;
    }
    catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
        // A previously detected exception with proper bean creation context already,
        // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
        throw ex;
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
            mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
    }
}

我们回到生命周期的步骤上来,其中第8步,第9步就在上面的这个方法当中

doCreateBean(beanName, mbdToUse, args)方法 : 对应第8步,第9步

其中的createBeanInstance()进行了该对象的实例化
在这里插入图片描述
上图说明spring是通过
createBeanInstance(beanName, mbd, args)
,完成了推断构造方法和实例化的事情

第10步:处理合并后的beanDefinition对象

在这里插入图片描述

第11步 : 进行了是否允许循环依赖的判断 : 如果支持则提前暴露一个工厂对象,注意是工厂对象

在这里插入图片描述
在这里插入图片描述

第12步:spring会判断是否需要完成属性注入(spring默认是需要的,但是程序员可以扩展spring,根据情况是否需要完成属性注入);如果需要则spring完成13步——属性注入,也就是所谓的自动注入;

在这里插入图片描述

第14,15,16步 : 判断bean的类型回调Aware接口,调用生命周期回调方法,如果需要代理则完成代理

  • 第14步:判断bean的类型回调Aware接口
  • 第15步:调用生命周期回调方法
  • 第16步:如果需要代理则完成代理
    在这里插入图片描述
    默认情况 , 至此一个bean完成初始化,第17步被put到单例池,也是对上文说的17个步骤的一个证明;这说明一个bean在spring容器当中被创建出来是有一个过程的,这个过程就是所谓的bean的生命周期,我们的循环依赖也是在这个生命周内完成的。下面我们具体来分析这些步骤

方法层面的SpringBean的生命周期过程

首先以下从方法层面讲解Bean的生命周期还是指的是singleton bean,对prototype bean来说,没有缓存池存放,当用户getBean时,每一次获取新的原型实例对象,在获得prototype bean的实例后,IOC容器就不再对当前实例进行管理,而是把管理权交由用户,此后再getBean生成的是新的实例。对于request/session/application/websocket 这几种scope的bean我们在此不谈。

而在不同的容器中,Bean的生命周期开始的时间不同 :

  • 对于ApplicationContext来说,当容器启动的时候,bean就已经实例化了。
  • 对于BeanFactory来说,直到调用**getBean()**方法的时候才进行实例化。

我们以getBean(),即进行Bean的实例化开始进行Bean的生命周期的讲述 :
在这里插入图片描述
对于上面的方法,我们归纳为以下几类 :

  • Bean自身的方法:比如构造函数、getter/setter以及init-method和destory-method所指定的方法等
  • Bean级生命周期方法:可以理解为Bean类直接实现接口的方法,比如BeanNameAware、BeanFactoryAware、ApplicationContextAware、InitializingBean、DisposableBean等方法,这些方法只对当前Bean生效
    容器级的方法(BeanPostProcessor一系列接口):主要是后处理器方法,比如上图的InstantiationAwareBeanPostProcessor、
  • BeanPostProcessor接口方法:这些接口的实现类是独立于bean的,并且会注册到Spring容器中。在Spring容器创建任何Bean的时候,这些后处理器都会发生作用,在Bean初始化前后进行方法的调用
  • 工厂后置处理器方法(BeanFactoryProcessor一系列接口):包括AspectJWeavingEnabler、CustomAutowireConfigurer、ConfigurationClassPostProcessor等。这些都是Spring框架中已经实现好的BeanFactoryPostProcessor,用来实现某些特定的功能。
    其中:

BeanPostProcessor和BeanFactoryProcessor的区别

BeanFactoryProcessor :
    public interface BeanFactoryPostProcessor {
    	//可以通过beanFactory获取bean定义信息
    	void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
    
    }

BeanFactoryPostProcessor接口是针对bean容器的,它的实现类可以在当前BeanFactory初始化(spring容器加载bean定义文件)后,bean实例化之前,即我们将BeanDefinition对象放置到beanDefinitionMap中以后修改bean的定义属性,达到影响之后实例化bean的效果。

也就是说,Spring允许BeanFactoryPostProcessor在容器实例化任何其它bean之前读取配置元数据,并可以根据需要进行修改,例如:

可以把bean的scope从singleton改为prototype,也可以把property的值给修改掉,甚至可以修改beanClass属性等等.

可以同时配置多个BeanFactoryPostProcessor,并通过设置’order’属性来控制各个BeanFactoryPostProcessor的执行次序。

Spring内置了一些BeanFactoryPostProcessor接口实现类,如下所示:
在这里插入图片描述

BeanPostProcessor :
public interface BeanPostProcessor {
     //bean初始化之前调用
	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}
    //bean初始化之后调用
	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}
}

BeanPostProcessor能在spring容器实例化bean之后,在执行bean的初始化方法前后,添加一些自己的处理逻辑。

初始化定义的方法 :

  • 实现InitializingBean接口的bean,对应方法为afterPropertiesSet
  • xml文件中定义,使用init-method属性设置
  • 注意 : 如果同时配置了,先执行接口的afterPropertiesSet方法,再执行配置文件中配置的init-method方法

如果自定义了多个的BeanPostProcessor的实现类,通过实现Ordered接口,设置order属性,可以按照顺序执行实现类的方法。

Spring内置了一些BeanPostProcessor接口实现类,如下所示:
在这里插入图片描述

ApplicationContext和BeanFactory的区别

区别点ApplicationContextBeanFactory
检测和加载BeanPostProcessor和BeanFactoryPostProcessor自动检测,加载调用方法手动注册和加载
对于后置处理器的自定义排序可以根据org.springframework.core包下的PriorityOrdered和Ordered来进行自定义排序只是使用默认的
定义及加载配置文件IOC容器基本实现,是Spring内部的使用接口,不提供开发人员进行使用;加载配置文件不会创建对象,在获取对象(或者使用的时候)才去创建对象.即延迟加载BeanFactory接口的子接口,提供更多更强大的功能,一般由开发人员进行使用,加载配置文件时候就会把在配置文件对象进行创建
功能扩展应用上下文,继承BeanFactory接口,它是Spring的一各更高级的容器,提供了更多的有用的功能,例如 : 国际化,访问资源,消息发送,AOP等等是Spring里面最低层的接口,提供了最简单的容器的功能,只提供了实例化对象和拿对象的功能

在开发中我们统一使用ApplicationContext进行加载配置文件,因为它功能更加地强大! ! !

Instantiation和Initialization

  • Instantiation : 实例化,指的是调用构造函数进行实例化,即我们所说的new 对象,底层是利用反射 + 构造器实现的
  • Initialization : 初始化,在Bean的声明周期中指的是init-method所指定的方法或者是InitializingBean.afterPropertiesSet()方法
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值