Spring之Bean(作用域、生命周期)

在spring中,哪些构成应用程序的主体以及被Spring IOC容器托管的对象叫做Bean

Bean的作用域概述

在Spring中,Bean默认都是单例的
在Java中,单例是基于JVM的,每个JVM中只有一个实例。
而Spring中的单例是基于BeanFactory的,也就是Spring IOC容器,Spring IOC的底层实质是一个工厂模式
Bean有五种作用域,其中三种仅在基于Web的应用中使用(无论使用的Web框架是什么),只能用在基于Web的SpringApplicationContext环境

下面简单的介绍一下五种作用域

类别简介
singleton在Spring IOC容器中仅存在一个Bean实例,Bean以单例方式存在,也是默认作用域
prototype每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时,都相当于执行new XXX()
request每次HTTP请求都会创建一个新的Bean,该作用域仅适用于WebApplicationContext环境
session同一个Http Session共享一个Bean,不同Session使用不同Bean,仅适用于WebApplicationContext
globalSession一般用于Portlet应用环境,该作用域仅适用于WebApplicationContext环境

格式(以singleton为例)

xml格式

<bean class="com.dean.controller" id="userController" scope="singleton"></bean>

注释格式

@Componet("userController")
@Scope(value="singleton")
//加在Controller类上

详细说说

Singleton

  • 当一个Bean的作用域为Singleton,那么Spring IOC容器中只会存在一个共享的bean实例,并且当所有对bean的请求,只要id与该bean定义相匹配,则只会返回bean的同一实例
  • Singleton是单例类型,即创建容器时就同时自动创建了一个Bean对象,不论是否被使用,它都已经存在了,每次获取到的对象也都是同一对象。
  • 可以对非线程安全的对象采用单实例模式
  • 虽然启动时,自动实例化bean会花费一些时间,但它却带来了两个好处:
    对bean提前的实例化操作,会及早发现一些潜在的配置问题
    Bean以缓存的方式运行,当运行到需要使用该bean的时候,就不需要再去实例化了,加快了运行效率

Prototype

  • 一个Bean定义对应多个对象实例
  • Prototype的作用域会导致在每次对该bean请求时,都会创建一个新的Bean实例,
  • 在创建容器时并没有实例化,当我们去获取Bean实例的时候才会去创建一个对象,而且每次获取到的对象都不是同一个对象
  • 有一点非常重要,Spring不能对一个prototype bean的整个生命周期负责:容器在初始化、装配或装配完一个prototype实例后,将它交给客户端,随后就对该prototype实例不闻不问了
  • 清除prototype作用域的对象并释放任何prototype bean所持有的昂贵资源,都是客户端代码的职责

Request

  • 在一次HTTP请求中,一个Bean定义对应一个实例
  • 每个Http请求都会有各自的bean实例
  • 针对每次HTTP请求,Spring容器会根据loginAction bean的定义创建一个全新的LoginAction bean实例,该LoginAction bean实例仅在当前Http request内有效,因此可以根据需要放心的更改所建实例的内部状态,而其他请求中根据loginAction bean定义所创建的实例,将不会看到这些特定于某个请求的状态变化

Session

  • 在一个Http Session中,一个Bean定义对应一个实例,作用域仅在Web的Spring ApplicationContext情形下有效
  • 针对某个Http Session,Spring容器会根据userPerferences bean定义创建一个全新的userPerferences bean实例,且该userPerferences bean仅在当前Http Session内有效
  • 根据需要放心的更改所创建实例的内部状态,而别的Http Session中根据userPreferences创建的实例,将不会看到这些特定于某个HTTP Session的状态变化

Global Session

  • 在一个全局Http Session中,一个bean定义对应一个实例。
  • 仅在基于portlet的web应用中才有意义Portlet规范定义了全局Session的概念

生命周期

以下图来自网络(图方便理解以下文字)

Bean实例化过程

在这里插入图片描述

  • Spring对bean进行实例化,默认bean的作用域是单例
  • Spring对bean进行依赖注入
  • 如果bean实现了BeanNameAware接口,Spring将bean的id传给setBeanName()方法
  • 如果bean实现了BeanFactoryAware接口,Spring调用setBeanFactory方法,将BeanFactory实例传进来
  • 如果bean实现了ApplicationContextAware接口,它的setApplicationContext()方法将被调用,将应用上下文的引用传入到bean中
  • 如果bean实现了BeanPostProcessor接口,它的postProcessBeforeInitialization方法将被调用
  • 如果bean实现了InitializingBean接口,spring将调用它的afterPropertiesSet接口方法,类似的如果bean使用了init-method属性声明了初始化方法,该方法也会调用
  • 如果bean实现BeanPostProcessor接口,它的postProcessAfterInitialization接口方法将被调用
  • 此时bean以及准备就绪,可以被应用程序使用,他们将一直驻留在应用上下文中,直到该应用上下文被销毁
  • 若bean实现了DisposableBean接口,spring将调用它的distroy()接口方法。同样的,如果bean使用了destroy-method属性声明了销毁方法,则该方法被调用
  • 实际上:很多时候并不会去实现上面所描述的哪些接口

Bean生命周期

  • init-method 指定一个方法,在实例化bean时,立即调用该方法
  • destroy-method 指定一个方法,只有从容器中移除bean之后,才能调用该方法
  • default-init-method和default-destory-method 在你有太多同名初始化和销毁方法的bean时,不需要在每一个bean上声明初始化和销毁方法,而是用上述两个设置默认值
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值