Spring--Bean的作用域及依赖问题

1.Bean的作用域(Spring 5.2.7.RELEASE)

ScopeDescription
singleton(单例)(默认的)在Spring IoC容器中,只会有唯一的一个bean实例。Spring采用的是双重校验锁来实现的单例模式。
prototype(原型)每次从Spring IoC容器中调用bean时,都返回新的实例,即调用getBean()时,都相当于执行new XxxBean()。
request(请求)一个bean定义对应于单个HTTP 请求的生命周期。也就是说,每个HTTP 请求都有一个bean实例,且该实例仅在这个HTTP 请求的生命周期里有效。该作用域仅适用于WebApplicationContext环境。
session(会话)一个bean 定义对应于单个HTTP Session 的生命周期,也就是说,每个HTTP Session 都有一个bean实例,且该实例仅在这个HTTP Session 的生命周期里有效。该作用域仅适用于WebApplicationContext环境。
application(应用)一个bean 定义对应于单个ServletContext 的生命周期。该作用域仅适用于WebApplicationContext环境。
websocket(网络套接字)一个bean 定义对应于单个websocket 的生命周期。该作用域仅适用于WebApplicationContext环境。

2.常用的作用域对比

2.1singleton(单例):

  • 对tomcat来说,每一个进来的请求(request)都需要一个线程,直到该请求结束。当Bean的作用域定义为singleton时,多个线程共用一个Bean实例。即减少了生成新实例对性能的消耗,也减少了垃圾回收的次数。

 

  • 当Bean被设置为单例非懒加载时,在spring容器创建时Bean就已经初始化。

 

  • 当Bean被设置为单例懒加载时,在第一次访问的时候初始化(如果该Bean被其他需要实例化的Bean引用到,Spring会忽略延迟实例化的设置)

  • 单例Bean在第一次生成实例时会将实例存放到ConcurrentHashMap对象中,之后每次用到该实例都会去map缓存里查找,所以获取速度很快。

  • 单例Bean的缺点是当Bean为有状态对象时(含属性的对象),无法做到线程安全。所以我们在日常开发中Controller,Service,Dao都只会定义方法,不会定义属性。

2.2prototype(原型)

  • prototype原型作用域下,每一个进来的请求(request)就实例化一个新的bean,没有缓存以及从缓存中查询的方法。

  • 当Bean的作用域定义为prototype原型时,默认采用懒加载的方式,即每次调用getBean()方法时才实例化。

3单例Bean中依赖原型Bean存在的问题

3.1问题复现

3.1.1作用域为原型的Dao

     3.1.2作用域为单例的Service

     3.1.3采用注解方式配置Spring容器

     3.1.4测试类

     3.1.5测试结果

3.2原因分析

单例(懒加载除外) Bean在 Spring容器初始化的时候就已经实例化完成,接下来只会从缓存中读取,而在单例 Bean 中,不管是依赖了单例 Bean还是原型 Bean,都是在 Spring 容器启动时实例化好了的,所以,我们看到两次打印 hashCode 的结果是一模一样的。

3.3解决方案

3.3.1放弃某些控制反转

通过实现ApplicationContextAware接口,作用是为了方便获得ApplicationContext中的所有bean。在单例Bean A每次需要原型Bean B实例时,对容器发出getBean(“B”)调用来让Bean A每次注入不同的Bean B,也就是说将Bean B的控制权重新交由我们自己来管理,而不是通过IoC自动注入。

3.3.2通过@Lookup注解实现方法注入

AutowiredAnnotationBeanPostProcessor 会检查类里面是否有方法添加了 @Lookup 这个注解,然后通过CGLib动态代理的方式,实现了getTestDao()抽象方法, 每次调用getTestDao()方法时都会调用getBean()方法去Spring容器重新获取Bean对象

4.参考资料

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值