聊聊spring中bean的作用域

简介: 今天分享一下spring bean的作用域,理解bean的作用域能够在使用过程中避免一些问题,bean的作用域也是spring bean创建过程中一个重要的点。

前言


今天分享一下spring bean的作用域,理解bean的作用域能够在使用过程中避免一些问题,bean的作用域也是spring bean创建过程中一个重要的点。


Spring bean的作用域类型


  • singleton(单例模式):在整个应用程序的生命周期中,只创建一个Bean实例。默认情况下,所有的Bean都是单例模式。

  • prototype(原型模式):每次请求Bean时都会创建一个新的实例。

  • request(请求模式):每次HTTP请求都会创建一个新的实例,该作用域仅适用于Web应用程序的Spring MVC应用程序。

  • session(会话模式):每个用户会话都有一个Bean实例,该作用域仅适用于Web应用程序的Spring MVC应用程序。

  • globalSession(全局会话模式):用于Portlet应用程序,一个全局会话有一个Bean实例。

  • application(应用程序模式):在Web应用程序上下文中,只创建一个Bean实例。

从上面我们能看出spring有很多种作用域,不过在实际使用中,我们基本都使用单例bean,这也是spring bean的默认作用域,单例bean能提高性能,因为全局只存在一个bean实例,而多例bean则每次请求都需要创建bean实例,当并发比较大的时候,就会比较影响性能,所以这时候就需要使用单例bean,但是单例bean可能会存在线程安全问题,当bean中存在可变的成员变量时,就会存在线程安全问题,而多例bean因为每次都会创建一个实例,所以不存在bean共享,就不存在线程安全问题。


使用作用域


现在我们基本都是使用SpringBoot,都是基于注解开发,我们可以使用注解@Scope设置bean的作用域,可以标注在类上和方法上。


标注方法


当我们使用@Bean定义Bean的时候,设置作用域可以直接在方法上面使用@Scope。


@Bean
@Scope("prototype")
public ScopeBean scopeBean(){
    return new ScopeBean();
}


标注类


使用@Component,@Service等注解定义bean时,设置作用域直接在类上添加@Scope。


@Component
@Scope("prototype")
public class ScopeBean {
}


获取bean和创建bean


如果是单例bean,在spring容器启动的时候会将Bean注册进IOC容器中,如果是多例bean,则不注册进IOC容器中。


bean在实例化前会把bean的基础信息组装成BeanDefinition,然后保存到BeanFactory中,如果是单例的bean,则会继续对bean处理后将bean注册到IOC容器中,如果是多例bean,则不注册进,当从IOC容器中获取bean时,如果是单例则从IOC容器中获取已经创建好的bean,如果是多例,则从BeanFactory中获取bean的定义信息BeanDefinition,然后重复和单例bean一样的步骤创建bean,只是创建后它不会保存进IOC容器,而是直接返回。


作用域和懒加载


如果bean设置为懒加载(Lazy)和单例bean,那么bean在spring启动时不会注册进容器中,而是等第一次获取bean的时候在创建bean,后面获取bean的时候再从IOC容器中获取,如果设置为多例bean,那么懒加载其实是没用的。


源码解析


源码比较简单,其实就是判断bean的类型,然后再进入不同的逻辑进行处理,在AbstractBeanFactory中,通过doGetBean()方法获取bean。


判断bean是否存在容器中


下图通过getSingleton()方法从singletonObjects中获取bean,如果获取到直接返回,代表bean已经创建过勒,已经存在与IOC容器中,singletonObjects就是整个spring中装bean实例的容器,他就是一个Map,spring整个bean的创建过程目的就是把bean放进它里面,所以spring简单得不行,但是更复杂得不行



bean不存在,则创建


下图有两个判断,判断单例bean和多例bean,单例bean会创建bean后然后加入到singletonObjects中,多例bean则直接返回,他们的创建都是走同一个方法,同一样的流程。



具体的创建流程就不一一细说,只是从大体思路去讲解,因为往里面说就贴出大篇代码,没啥必要,感兴趣可以去看源码。


总结


上面说了bean的作用域类型,并对每种作用域类型进行分析,最常用的其实就是单例,并对多例和单例使用过程中的一些注意事项进行讲解,接着说了怎么使用作用域,还有懒加载和作用域的关联,并对bean的创建和获取从源码和白话进行大体的分析。


今天的分享就到这里,感谢你的观看,我们下期见!


目录
相关文章
|
17小时前
|
Java 应用服务中间件 Spring
Spring系列文章:Bean的作⽤域
Spring系列文章:Bean的作⽤域
|
17小时前
|
Java Spring 容器
Spring系列文章:Bean的获取⽅式
Spring系列文章:Bean的获取⽅式
|
17小时前
|
缓存 Java Spring
Spring 框架中 Bean 的生命周期
Spring 框架中 Bean 的生命周期
38 1
|
17小时前
|
安全 Java Spring
Spring框架中的单例Bean是线程安全的吗?
Spring框架中的单例Bean是线程安全的吗?
8 1
|
17小时前
|
消息中间件 安全 Java
在Spring Bean中,如何通过Java配置类定义Bean?
【4月更文挑战第30天】在Spring Bean中,如何通过Java配置类定义Bean?
21 1
|
17小时前
|
XML Java 数据格式
Spring Bean
【4月更文挑战第30天】Spring Bean
17 0
|
17小时前
|
前端开发 Java 数据格式
【Spring系列笔记】定义Bean的方式
在Spring Boot应用程序中,定义Bean是非常常见的操作,它是构建应用程序的基础。Spring Boot提供了多种方式来定义Bean,每种方式都有其适用的场景和优势。
32 2
|
17小时前
|
XML Java 数据格式
谈谈 Spring 中 Bean 的生命周期?
谈谈 Spring 中 Bean 的生命周期?
20 1
|
17小时前
|
XML Java 数据格式
Spring Bean的定义(含创建Bean的三种方式)
Spring Bean的定义(含创建Bean的三种方式)
|
17小时前
|
XML 人工智能 Java
Spring Bean名称生成规则(含源码解析、自定义Spring Bean名称方式)
Spring Bean名称生成规则(含源码解析、自定义Spring Bean名称方式)