高级Spring之Scope 详解
在当前版本的 Spring 和 Spring Boot 程序中,支持五种 Scope
singleton,容器启动时创建(未设置延迟),容器关闭时销毁
prototype,每次使用时创建,不会自动销毁,需要调用 DefaultListableBeanFactory.destroyBean(bean) 销毁
request,每次请求用到此 bean 时创建,请求结束时销毁
session,每个会话用到此 bean 时创建,会话结束时销毁
application,web 容器用到此 bean 时创建,容器停止时销毁
有些文章提到有 globalSession 这一 Scope,也是陈旧的说法,目前 Spring 中已废弃
但要注意,如果在 singleton 注入其它 scope 都会有问题,解决方法有
@Lazy
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
ObjectFactory
ApplicationContext.getBean
案例演示:request, session, application 作用域
/*singleton, prototype, request, session, applicationjdk >= 9 如果反射调用 jdk 中方法,会报非法访问异常jdk <= 8 不会有问题演示 request, session, application 作用域打开不同的浏览器, 刷新 http://localhost:8080/test 即可查看效果如果 jdk > 8, 运行时请添加 --add-opens java.base/java.lang=ALL-UNNAMED*/
@SpringBootApplication
public class A08 {public static void main(String[] args) {SpringApplication.run(A08.class, args);}
}
使用不同作用域的Bean如下:
BeanForApplication
@Scope("application")
@Component
public class BeanForApplication {private static final Logger log = LoggerFactory.getLogger(BeanForApplication.class);@PreDestroypublic void destroy() {log.debug("destroy");}
}
BeanForRequest
@Scope("request")
@Component
public class BeanForRequest {private static final Logger log = LoggerFactory.getLogger(BeanForRequest.class);@PreDestroypublic void destroy() {log.debug("destroy");}}
BeanForSession
@Scope("session")
@Component
public class BeanForSession {private static final Logger log = LoggerFactory.getLogger(BeanForSession.class);@PreDestroypublic void destroy() {log.debug("destroy");}
}
使用的Bean使用代码如下:
@RestController
public class MyController {@Lazy@Autowiredprivate BeanForRequest beanForRequest;@Lazy@Autowiredprivate BeanForSession beanForSession;@Lazy@Autowiredprivate BeanForApplication beanForApplication;@GetMapping(value = "/test", produces = "text/html")public String test(HttpServletRequest request, HttpSession session) {ServletContext sc = request.getServletContext();String sb = "<ul>" +"<li>" + "request scope:" + beanForRequest + "</li>" +"<li>" + "session scope:" + beanForSession + "</li>" +"<li>" + "application scope:" + beanForApplication + "</li>" +"</ul>";return sb;}}
单例使用其他的例,都得使用@azy注解,否则会失效
分析 - singleton 注入其它 scope 失效
以单例注入多例为例
有一个单例对象 E
@Component
public class E {private static final Logger log = LoggerFactory.getLogger(E.class);private F f;public E() {log.info("E()");}@Autowiredpublic void setF(F f) {this.f = f;log.info("setF(F f) {}", f.getClass());}public F getF() {return f;}
}
要注入的对象 F 期望是多例
@Component
@Scope("prototype")
public class F {private static final Logger log = LoggerFactory.getLogger(F.class);public F() {log.info("F()");}
}
测试
E e = context.getBean(E.class);
F f1 = e.getF();
F f2 = e.getF();
System.out.println(f1);
System.out.println(f2);
输出
com.tangyuan.demo.cycle.F@6622fc65
com.tangyuan.demo.cycle.F@6622fc65
发现它们是同一个对象,而不是期望的多例对象
对于单例对象来讲,依赖注入仅发生了一次,后续再没有用到多例的 F,因此 E 用的始终是第一次依赖注入的 F
解决
仍然使用 @Lazy 生成代理
代理对象虽然还是同一个,但当每次使用代理对象的任意方法时,由代理创建新的 f 对象
@Component
public class E {@Autowired@Lazypublic void setF(F f) {this.f = f;log.info("setF(F f) {}", f.getClass());}// ...
}
注意
@Lazy 加在也可以加在成员变量上,但加在 set 方法上的目的是可以观察输出,加在成员变量上就不行了
@Autowired 加在 set 方法的目的类似
输出
E: setF(F f) class com.itheima.demo.cycle.F$$EnhancerBySpringCGLIB$$8b54f2bc
F: F()
com.tangyuan.demo.cycle.F@3a6f2de3
F: F()
com.tangyuan.demo.cycle.F@56303b57
从输出日志可以看到调用 setF 方法时,f 对象的类型是代理类型
4种解决方法
@Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
@Component
public class F2 {
}
@Autowiredprivate ObjectFactory<F3> f3;public F3 getF3() {return f3.getObject();}
@Autowiredprivate ApplicationContext context;public F4 getF4() {return context.getBean(F4.class);}
收获
高级Spring之Scope 详解相关推荐
- Spring bean - scope详解
Scope是定义Spring如何创建bean的实例的. 在创建bean的时候可以带上scope属性,scope有下面几种类型. Singleton 这也是Spring默认的scope,表示Spri ...
- Spring Boot 配置文件详解
2019独角兽企业重金招聘Python工程师标准>>> 第二篇 : Spring Boot配置文件详解 文章首发于微信公众号<程序员果果> 地址:https://mp.w ...
- Spring的lazy-init详解
Spring中lazy-init详解 ApplicationContext实现的默认行为就是在启动服务器时将所有singleton bean提前进行实例化 (也就是依赖注入).提前实例化意味着作为初始 ...
- 一文搞定 Spring Data Redis 详解及实战
转载自 一文搞定 Spring Data Redis 详解及实战 SDR - Spring Data Redis的简称. Spring Data Redis提供了从Spring应用程序轻松配置和访问 ...
- Spring Boot 单元测试详解+实战教程
转载自 Spring Boot 单元测试详解+实战教程 Spring Boot 的测试类库 Spring Boot 提供了许多实用工具和注解来帮助测试应用程序,主要包括以下两个模块. spring ...
- 《深入理解 Spring Cloud 与微服务构建》第十六章 Spring Boot Security 详解
<深入理解 Spring Cloud 与微服务构建>第十六章 Spring Boot Security 详解 文章目录 <深入理解 Spring Cloud 与微服务构建>第十 ...
- 全面的Spring Boot配置文件详解
全面的Spring Boot配置文件详解 Spring Boot在工作中是用到的越来越广泛了,简单方便,有了它,效率提高不知道多少倍.Spring Boot配置文件对Spring Boot来说就是入门 ...
- Spring启动过程详解
Spring启动过程详解 前言 spring容器启动过程 AnnotationConfigApplicationContext 有参数构造方法 无参数构造 AnnotatedBeanDefinitio ...
- Spring Security应用详解(集成SpringBoot)
Spring Security应用详解 集成SpringBoot 工作原理 认证流程 授权流程 集成SpringBoot 1.Spring Boot介绍 Spring Boot是一套Spring的快速 ...
最新文章
- 【opencv4】opencv视频教程 C++(opencv教程)2、加载imread()(以灰度加载),修改,保存图像
- python支持list类型吗_Python Numpy不支持的操作数类型“list”“list”
- 初一模拟赛总结(2019.5.25)
- 经典面试题(22):以下代码将输出的结果是什么?
- 携程Apollo分布式配置中心搭建指南
- php页面设定语言,php实现获取及设置用户访问页面语言类,php页面_PHP教程
- qq html消息,类似于QQ新消息提醒-前端
- “衰亡”的雅虎:30 亿用户账号全部泄漏还能怎么活?
- 为小程序添加底部导航
- 一些软件工程的基础知识
- java 打包加密_java打包、加密、发布(源代码保护)
- PR 2019 快速入门(8)
- fpga如何约束走线_FPGA入门之我见- 布局布线(place route,PAR)
- 保利威视后台编辑FLASH播放器
- 光阴似锦,关于身体保养的那些事
- 4:3 背景图片素材
- 中国人民大学计算机专硕好考吗,干货:中国人民大学考研复试成功经验分享,值得收藏!...
- 3D 建模费时费力,Python 让照片秒变模型
- MySQL(查询语句,关键字)
- 小程序获取本地存储数据,然后传参的时候是上次请求的id
热门文章
Scope是定义Spring如何创建bean的实例的. 在创建bean的时候可以带上scope属性,scope有下面几种类型. Singleton 这也是Spring默认的scope,表示Spri ...
2019独角兽企业重金招聘Python工程师标准>>> 第二篇 : Spring Boot配置文件详解 文章首发于微信公众号<程序员果果> 地址:https://mp.w ...
Spring中lazy-init详解 ApplicationContext实现的默认行为就是在启动服务器时将所有singleton bean提前进行实例化 (也就是依赖注入).提前实例化意味着作为初始 ...
转载自 一文搞定 Spring Data Redis 详解及实战 SDR - Spring Data Redis的简称. Spring Data Redis提供了从Spring应用程序轻松配置和访问 ...
转载自 Spring Boot 单元测试详解+实战教程 Spring Boot 的测试类库 Spring Boot 提供了许多实用工具和注解来帮助测试应用程序,主要包括以下两个模块. spring ...
<深入理解 Spring Cloud 与微服务构建>第十六章 Spring Boot Security 详解 文章目录 <深入理解 Spring Cloud 与微服务构建>第十 ...
全面的Spring Boot配置文件详解 Spring Boot在工作中是用到的越来越广泛了,简单方便,有了它,效率提高不知道多少倍.Spring Boot配置文件对Spring Boot来说就是入门 ...
Spring启动过程详解 前言 spring容器启动过程 AnnotationConfigApplicationContext 有参数构造方法 无参数构造 AnnotatedBeanDefinitio ...
Spring Security应用详解 集成SpringBoot 工作原理 认证流程 授权流程 集成SpringBoot 1.Spring Boot介绍 Spring Boot是一套Spring的快速 ...