《SpringBoot 3:入门与应用实战》第 3 章 IOC 容器中的 Bean 阅读笔记 2
《SpringBoot 3入门与应用实战》第 3 章 IOC 容器中的 Bean 阅读笔记 23.2 Bean 的作用域作用域是一个很关键的概念理解这个概念对学习 Spring Framework 中 Bean 的作用域很有帮助。3.2.1 理解作用域Java 语言的基础概念成员变量、方法变量、局部变量。3.2.2 内置的作用域Spring Framework 中内置了 6 种作用域6.x版本。作用域类型概述singleton一个 IOC 容器中只有一个proptype每次获取新创建一个request一次请求创建一个session一个会话创建一个application一个 Web 应用创建一个websocket一个 websocket 会话创建一个3.2.3 单实例 (singleton)Spring Framework 中默认所有的 Bean 都是单实例的即一个 IOC 容器中只有一个。1.创建 Bean配置类先创建两个简单类 Child 和 Toy。接下来开始编写注解配置类为了演示 Toy 在 IOC 容器中只产生了一个 Bean我们在配置类 BeanScopeConfiguration 中注入两个 Child 类型的 Bean都注入 Toy 类型的 Bean。packagecom.yangjunbo.bean.scope.examplea;importorg.springframework.stereotype.Component;ComponentpublicclassToy{}packagecom.yangjunbo.bean.scope.examplea;publicclassChild{privateToytoy;publicvoidsetToy(Toytoy){this.toytoy;}OverridepublicStringtoString(){returnChild{toytoy};}}packagecom.yangjunbo.bean.scope.examplea;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.ComponentScan;importorg.springframework.context.annotation.Configuration;ConfigurationComponentScan(com.yangjunbo.bean.scope.examplea)publicclassBeanScopeConfiguration{BeanpublicChildchild1(Toytoy){ChildchildnewChild();child.setToy(toy);returnchild;}BeanpublicChildchild2(Toytoy){ChildchildnewChild();child.setToy(toy);returnchild;}}2.测试运行启动类 BeanScopeAnnoApplication使用注解驱动 IOC 容器并从容器中取出所有 Child 对象打印其内部的 Toy 对象并观察。运行 main 方法控制台中打印的两个 Child 中持有的 Toy 是同一个证明默认情况下 IOC 容器中的 Bean 作用域的确是单实例的。packagecom.yangjunbo.bean.scope.examplea;importorg.springframework.context.ApplicationContext;importorg.springframework.context.annotation.AnnotationConfigApplicationContext;publicclassBeanScopeAnnoApplication{publicstaticvoidmain(String[]args)throwsException{ApplicationContextctxnewAnnotationConfigApplicationContext(BeanScopeConfiguration.class);ctx.getBeansOfType(Child.class).forEach((name,child)-{System.out.println(name : child);});}}3.2.4 原型 (prototype)如果连续两次调用 getBean 方法那么应当创建两个不同的 Bean向两个不同的 Bean 中注入两次也应当注入两个不同的 Bean。1.原型 Bean 效果演示Toy 类上标注一个额外的注解 Scope并声明为原型类型。在接口 ConfigurableBeanFactory 中定义好了常量如果担心声明作用域时拼错单词建议直接引用对应的常量。其他代码不需要改变直接运行 BeanScopeAnnoApplication 的 main 方法发现控制台打印的两个 Toy 确实不同。2.原型 Bean 的创建时机对于单实例 Bean 的创建时机我们已经了解在 ApplicationContext 被初始化时就已经创建完毕那么原型 Bean 的创建时机是什么原型 Bean 都是在获取时创建的。验证方法可以给 Toy 类中添加一个无参构造方法构造方法中打印信息到控制台。修改启动类BeanScopeAnnoApplication如果只做组件扫描不加载配置类这样就相当于只有一个 Toy 类被扫描进去了Child 不会注册到 IOC 容器中Toy 类的构造方法没有打印说明容器初始化时没有创建 Toy Bean。而如果不修改启动类以 BeanScopeConfiguration 配置类驱动 IOC 容器则控制台中可以看到两次 Toy 构造方法的打印。packagecom.yangjunbo.bean.scope.examplea;importorg.springframework.context.ApplicationContext;importorg.springframework.context.annotation.AnnotationConfigApplicationContext;publicclassBeanScopeAnnoApplication{publicstaticvoidmain(String[]args)throwsException{ApplicationContextctxnewAnnotationConfigApplicationContext(BeanScopeConfiguration.class);ctx.getBeansOfType(Child.class).forEach((name,child)-{System.out.println(name : child);});System.out.println(---------------------不加载配置类---------------------);ApplicationContextctx2newAnnotationConfigApplicationContext();System.out.println(---------------------加载配置类---------------------);ApplicationContextctx3newAnnotationConfigApplicationContext(BeanScopeConfiguration.class);}}3.2.5 Web 中的扩展作用域request每次客户端向 Web 应用服务器发起一次请求Web 服务器接收到请求后由 Spring Framework 生成一个 Bean直到请求结束后销毁。session每个客户端在与 Web 应用服务器发起会话后Spring Framework 会为之生成一个 Bean直到会话过期后销毁。application每个 Web 应用在启动时Spring Framework 会生成一个 Bean直到应用停止后销毁。websocket每个客户端在与 Web 应用服务器建立 WebSocket 长连接时Spring Framework 会为之生成一个 Bean直到断开连接后销毁。