当前位置:   article > 正文

Spring bean的生命周期和作用域_springbeen周期和作用域

springbeen周期和作用域

一、Spring框架背景知识:

1、关键词:轻量级框架,IOC容器(控制反转),AOP(面向切面编程),事务支持

2、主要内容:

从下往上:Test→支持Junit测试

Core Container(Beans, Core, Context)→IOC

AOP, ASpects→ AOP

3、IOC(Inversion of Control)控制反转–依赖注入(Independency Injection)

3.1、IOC

对象由原来程序本身创建,变成了程序接受对象;

层和层解耦分离,没有直接依赖关系;

bean: java对象

控制的内容: 谁来控制对象的创建(传统的应用程序对象的创建是由程序本身控制的,使用spring之后,由spring创建对象)

反转:程序本身创建对象,变为程序被动接受spring创建的对象。

IOC的实现是通过IOC容器实现的–BeanFactory

IOC创建对象的方式:

  1. 通过无参构造方法创建
  2. 通过有参构造方法创建
  3. 通过工厂方法来创建对象
    1. 静态工厂
    2. 动态工厂

3.2、依赖注入(Dependency Injection)

依赖:指bean对象的创建依赖于容器,Bean对象的依赖资源

注入:指bean对象依赖的资源由容器来设置和装配

Spring注入:

  1. 构造器注入
  2. setter注入

4、bean的自动装配

简化spring配置文件

4.1、Autowiring

  1. byName(set方法后面的名称)
  2. byType
  3. constructor

二、Bean的作用域

scope

description

singleton(Default)(默认)单例,整个容器(Spring bean容器)中只有一个对象实例
prototype原型,每次获取bean都产生一个新的对象
request每次HTTP请求时,新建一个对象,仅适用于基于Web的Spring ApplicationContext环境
session每次HTTP会话新建一个对象,仅适用于基于Web的Spring ApplicationContext环境
application一个ServletContext拥有一个对象,仅适用于基于Web的Spring ApplicationContext环境
websocket每次WebSocket新建一个对象,仅适用于基于Web的Spring ApplicationContext环境

1、Singleton

Spring中的默认作用域;

在创建起容器时就同时自动创建了bean的对象,不管是否使用,都存在,而且每次获取到的对象都是同一个对象;

可以通过指定lazy-init="true"来延迟初始化bean,这时候,只有在第一次获取bean时才会初始化bean;

优点:减少了新生成实例的消耗,减少jvm垃圾回收,可以快速获取到Bean

缺点:线程不安全

当看到这里的时候,很显然,会有一个疑问,既然Spring所有的bean默认都是单例的,那么是怎么保证线程安全的呢?

根据《深入理解JVM虚拟机》2.2.2节Java虚拟机栈

每个方法被执行的时候,Java虚拟机都 会同步创建一个栈帧[1](Stack Frame)用于存储局部变量表、操作数栈、动态连接、方法出口等信息。每一个方法被调用直至执行完毕的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。

每次执行方法时,都有自己的栈帧,这是线程隔离的;因此对于所有无状态单例都是线程安全的。

无状态:不会保存数据

有状态: 会保存数据

2、Prototype

Prototype作用域的bean在每次对该bean请求(将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法)时都会创建一个新的bean实例。

在创建容器时并没有实例化,只有当我们获取bean的时候才会去创建一个对象,而且每次获取到的对象都不是同一个。

因此,对于有状态的bean应该使用Prototype,无状态的bean可以使用Singleton。

三、Bean的生命周期

Bean的生命周期概括:

  1. 实例化-Instantiation
  2. 属性赋值-Populate
  3. 初始化-Initialization
  4. 销毁-Destruction

 

以上总结的生命周期主要是 AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)类的doCreateBean方法

AbstractAutowireCapableBeanFactory.java 展开源码

  1. /**
  2. * Actually create the specified bean. Pre-creation processing has already happened
  3. * at this point, e.g. checking {@code postProcessBeforeInstantiation} callbacks.
  4. * <p>Differentiates between default bean instantiation, use of a
  5. * factory method, and autowiring a constructor.
  6. * @param beanName the name of the bean
  7. * @param mbd the merged bean definition for the bean
  8. * @param args explicit arguments to use for constructor or factory method invocation
  9. * @return a new instance of the bean
  10. * @throws BeanCreationException if the bean could not be created
  11. * @see #instantiateBean
  12. * @see #instantiateUsingFactoryMethod
  13. * @see #autowireConstructor
  14. */
  15. protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
  16. throws BeanCreationException {
  17. // Instantiate the bean.实例化
  18. BeanWrapper instanceWrapper = null;
  19. if (mbd.isSingleton()) {
  20. //
  21. instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
  22. }
  23. if (instanceWrapper == null) {
  24. instanceWrapper = createBeanInstance(beanName, mbd, args);
  25. }
  26. Object bean = instanceWrapper.getWrappedInstance();
  27. Class<?> beanType = instanceWrapper.getWrappedClass();
  28. if (beanType != NullBean.class) {
  29. mbd.resolvedTargetType = beanType;
  30. }
  31. // Allow post-processors to modify the merged bean definition.
  32. synchronized (mbd.postProcessingLock) {
  33. if (!mbd.postProcessed) {
  34. try {
  35. applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
  36. }
  37. catch (Throwable ex) {
  38. throw new BeanCreationException(mbd.getResourceDescription(), beanName,
  39. "Post-processing of merged bean definition failed", ex);
  40. }
  41. mbd.postProcessed = true;
  42. }
  43. }
  44. // Eagerly cache singletons to be able to resolve circular references
  45. // even when triggered by lifecycle interfaces like BeanFactoryAware.
  46. boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
  47. isSingletonCurrentlyInCreation(beanName));
  48. if (earlySingletonExposure) {
  49. if (logger.isTraceEnabled()) {
  50. logger.trace("Eagerly caching bean '" + beanName +
  51. "' to allow for resolving potential circular references");
  52. }
  53. addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
  54. }
  55. // Initialize the bean instance.
  56. Object exposedObject = bean;
  57. try {
  58. // 属性填充
  59. populateBean(beanName, mbd, instanceWrapper);
  60. // 初始化
  61. // 完成属性依赖注入后,进一步初始化Bean
  62. // 具体进行了以下操作:
  63. // 1.若实现了BeanNameAware, BeanClassLoaderAware,BeanFactoryAwareAware等接口,则注入相关对象
  64. // 2.遍历后置处理器,调用实现的postProcessBeforeInitialization方法,
  65. // 3.如果实现了initialzingBean,调用实现的 afterPropertiesSet()
  66. // 4.如果配置了init-mothod,调用相应的init方法
  67. // 5.遍历后置处理器,调用实现的postProcessAfterInitialization
  68. exposedObject = initializeBean(beanName, exposedObject, mbd);
  69. }
  70. catch (Throwable ex) {
  71. if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
  72. throw (BeanCreationException) ex;
  73. }
  74. else {
  75. throw new BeanCreationException(
  76. mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
  77. }
  78. }
  79. if (earlySingletonExposure) {
  80. Object earlySingletonReference = getSingleton(beanName, false);
  81. if (earlySingletonReference != null) {
  82. if (exposedObject == bean) {
  83. exposedObject = earlySingletonReference;
  84. }
  85. else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
  86. String[] dependentBeans = getDependentBeans(beanName);
  87. Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
  88. for (String dependentBean : dependentBeans) {
  89. if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
  90. actualDependentBeans.add(dependentBean);
  91. }
  92. }
  93. if (!actualDependentBeans.isEmpty()) {
  94. throw new BeanCurrentlyInCreationException(beanName,
  95. "Bean with name '" + beanName + "' has been injected into other beans [" +
  96. StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
  97. "] in its raw version as part of a circular reference, but has eventually been " +
  98. "wrapped. This means that said other beans do not use the final version of the " +
  99. "bean. This is often the result of over-eager type matching - consider using " +
  100. "'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
  101. }
  102. }
  103. }
  104. }
  105. // Register bean as disposable.
  106. // 如果符合 bean 的销毁条件,则执行单例bean 的销毁工作
  107. try {
  108. registerDisposableBeanIfNecessary(beanName, bean, mbd);
  109. }
  110. catch (BeanDefinitionValidationException ex) {
  111. throw new BeanCreationException(
  112. mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
  113. }
  114. return exposedObject;
  115. }

initializeBean 展开源码

  1. protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
  2. if (System.getSecurityManager() != null) {
  3. AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
  4. invokeAwareMethods(beanName, bean);
  5. return null;
  6. }, getAccessControlContext());
  7. }
  8. else {
  9. // 执行Aware
  10. invokeAwareMethods(beanName, bean);
  11. }
  12. Object wrappedBean = bean;
  13. if (mbd == null || !mbd.isSynthetic()) {
  14. // 初始化前BeanPostProcessors
  15. wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
  16. }
  17. try {
  18. // 初始化
  19. invokeInitMethods(beanName, wrappedBean, mbd);
  20. }
  21. catch (Throwable ex) {
  22. throw new BeanCreationException(
  23. (mbd != null ? mbd.getResourceDescription() : null),
  24. beanName, "Invocation of init method failed", ex);
  25. }
  26. if (mbd == null || !mbd.isSynthetic()) {
  27. // 初始化后BeanPostProcessors
  28. wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
  29. }
  30. return wrappedBean;
  31. }

1、首先思考一个问题,既然说Spring大部分都是单例,只要不是懒加载的单例,在容器启动后就自动创建了,那是什么时候创建的?

在该方法上打断点,查看调用栈可以发现,main方法开始后,层层调用,在AbstractApplicationContext类的refresh()方法里面:

 

// Instantiate all remaining (non-lazy-init) singletons.

// 实例化非懒加载的单例bean

finishBeanFactoryInitialization(beanFactory);

然后调用到doCreateBean();

Demo实现测试:

Demo

package com.example.demo.Entity;

import org.springframework.beans.factory.InitializingBean;

import javax.annotation.PostConstruct;

import javax.annotation.PreDestroy;

/**

 * @Version 1.0

 * @Author LifeBean

 * @Date 2022/3/30 6:43 PM

 * @Description

 */

public class LifeBean implements InitializingBean {

    private String name;

    public LifeBean(){

        System.out.println("LifeBean()构造函数");

    }

    public String getName() {

        return name;

    }

    public void setName(String name) {

        System.out.println("setName()" + name);

        this.name = name;

    }

    @Override

    public void afterPropertiesSet() throws Exception {

        System.out.println("this is after properties set");

    }

    public void init(){

        System.out.println("this is init of lifeBean");

    }

    public void destroy(){

        System.out.println("this is destory of lifeBean " + this);

    }

    @PostConstruct

    public void post() {

        System.out.println("this is post constructor of lifeBean");

    }

    @PreDestroy

    public void pre() {

        System.out.println("this is pre destroy of lifeBean");

    }

}

配置类

package com.example.demo.Config;

import com.example.demo.Entity.LifeBean;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

/**

 * @Version 1.0

 * @Author LifeBeanConfig

 * @Date 2022/4/1 7:29 PM

 * @Description

 */

@Configuration

public class LifeBeanConfig {

    @Bean(initMethod = "init", destroyMethod = "destroy")

    LifeBean lifeBean() {

        LifeBean  lifeBean = new LifeBean();

        lifeBean.setName("testAnnotation");

        return lifeBean;

    }

}

测试代码

package com.example.demo;

import com.example.demo.Entity.LifeBean;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.context.ApplicationContext;

@SpringBootApplication

public class Demo2Application {

    public static void main(String[] args) {

       ApplicationContext applicationcontext = SpringApplication.run(Demo2Application.class, args);

        LifeBean life1 = (LifeBean) applicationcontext.getBean("lifeBean");

        System.out.println(life1.getName());

    }

}

运行测试代码,可以看到输出:

可以看到符合生命周期的轨迹。

以上是一个单例bean的生命周期,将bean的type改成prototype,可以发现当容器关闭时,作为prototype作用域的bean,predestroy方法和destroy方法都没有被调用,spring不对prototype bean的整个生命周期负责。

待解决的问题:

  1. 循环依赖

参考

1.Introduction to the Spring Framework

2.如何记忆 Spring Bean 的生命周期

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小舞很执着/article/detail/740606
推荐阅读
相关标签
  

闽ICP备14008679号