首页 > 其他分享 >聊聊spring中bean的作用域

聊聊spring中bean的作用域

时间:2023-04-06 09:27:48浏览次数:68  
标签:作用域 spring Bean 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的创建和获取从源码和白话进行大体的分析。

标签:作用域,spring,Bean,bean,单例,创建
From: https://www.cnblogs.com/myblue999/p/17291603.html

相关文章

  • springboot项目图片不显示的问题
    首先确认你的图片路径是对的那么大概率就是浏览器缓存的原因,因为页面直接用的是缓存的旧数据,所以显示不出来。再不修改浏览器设置的情况下,最简单的办法就是直接项目在pom.xml文件里引入devtools如下:<dependency><groupId>org.springframework.boot</groupId><artifactId>sp......
  • SpringBoot如何进行限流,老鸟们还可以这样玩!
    大家好,我是飘渺。在SpringBoot如何进行限流,老鸟们都这么玩的!一文中我们详细介绍了为什么需要对接口进行限流,也介绍了常见的限流算法,最后还基于Guava工具类实现了接口限流。但是这种方式有个问题,无法实现分布式限流。那今天我们来利用Redis+Lua来实现分布式限流。Lua脚本......
  • Java SpringBoot Bean InitializingBean
    Spring中有两种类型的Bean,一种是普通Bean,另一种是工厂Bean,即FactoryBean。工厂Bean跟普通Bean不同,其返回的对象不是指定类的一个实例,其返回的是该工厂Bean的getObject方法所返回的对象。Spring初始化bean有两种方式:实现InitializingBean接口,实现afterPropertiesSet方法。(比通过......
  • spring事务
      步骤;1.在要开事务的方法上面加一个@Transactional  2.设置事务管理器:  3.在config里enable一下事务管理,写个@EnableTransactionManagement        角色:  spring事务相关配置: ......
  • 解决在创建springboot项目中遇到:Error:(3, 32) java: 无法访问org.springframework.bo
    解决在创建springboot项目中遇到:Error:(3,32)java:无法访问org.springframework.boot.SpringApplication File--->ProjectStructure    选择对应版本        File--->Settings--->Build,Execution,Deployment    修改对应版本 ......
  • python基础七(函数名称空间及作用域、函数对象、函数嵌套、闭包函数、装饰器)
    一名称空间(namespaces):存放名字的地方,是对栈区的划分。 有了名称空间之后,就可以在栈区中存放相同的名字,详细的名称空间。分三种1.1内建名称空间存放的名字:存放的python解释器内置的名字print<built-infunctionprint>存活周期:python解释器启动则产生,python解释器关闭则销毁......
  • Spring框架学习
    一、第一部分:SpringIoC&DI1.Spring概述1.1Spring是什么(1)Spring是分层的JavaSE/EE应用full-stack轻量级开源框架;(2)Spring以IoC和AOP为内核;InverseOfControl:反转控制AspectOrientedProgramming:面向切面编程(3)提供了展现层SpringMVC和持久层SpringJDBC......
  • SpringBoot启动流程
    启动类@SpringBootApplicationpublicclassApp{publicstaticvoidmain(String[]args){ SpringApplication.run(App.class,args);}}@SpringBootApplication对于一个SpringBoot程序的启动首先需要一个加了@SpringBootApplication注解的启动类。@Spr......
  • Failed to start bean 'documentationPluginsBootstrapper';nested exception is jav
    报错:Failedtostartbean‘documentationPluginsBootstrapper’;nestedexceptionisjava.lang.NullPointerException错误项目版本:springboot最新版本<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-sta......
  • 设计模式(三十二)----综合应用-自定义Spring框架-自定义Spring IOC-自定义Spring IOC
    1自定义SpringIOC总结1.1使用到的设计模式工厂模式。这个使用工厂模式+配置文件的方式。单例模式。SpringIOC管理的bean对象都是单例的,此处的单例不是通过构造器进行单例的控制的,而是spring框架对每一个bean只创建了一个对象。模板方法模式。AbstractApplicationC......