spring bean的作用域配置及相关问题

一、spring的作用域分五种:

1.singleton: bean的默认作用域,spring容器内存在一个实例。(用这个作用域有一个缺点待补)。

2.prototype:一次调用,产生一次实例。原话是every be requested。

3.reuqest:针对于http,一次请求一个实例。

3.session:针对于http,同一个session一个实例。原话是 each HTTP session by the web container.

4.globalSession:原话 beans for Portlet applications.单点登录。理解上,跨域session同一实例。

二、当前遇到的需求,一个方法,入参和返回值格式比较固定,但是内容涉及计算等,相对复杂,所以要做成模版式。每次调用这个方法都返回一个新的实例,想过用ThreadLocal,模拟spring jdbcTemplate,但是存在一个问题,一个方法,如果内部不单独起线程,那么就是一个线程,我可能会在方法内部调用n(n>=1)次方法,所以ThreadLocal不可取。利用spring bean's prototype scope 可以达到我想要的目的(每次调用都会产生一个实例)。

三、模拟模版类,将模版类简化为,里面有一个共享变量(非 volatile),一个方法,然后将当前对象注入spring容器中。如下:

bean的生成周期大家都知道,我没有给init-method 而直接做一个无参构造函数代替。


我要做的实验就是,在另一个类中注入此bean,然后连续调用say方法,看bean是否实例化指定次数,共享变量是否依次增加。


如上图,是测试类,当前项目基于springboot。测试结果如下


并没有得到我们想要的结果。实例化两次依据日志个人分析:第一次注解@Service将当前类注入到bean中,当然如果你指定lazy的话应该不会加载。第二次,@Autowired 注入。因为我在方法内部第一行打的断点。有好友说,是@Autowired的问题,应该每调一次方法 就@Autowired一次,我试过了不行,原理应该是,当前bean已经交给spring管理,所以,多少次注入结果都是一样的。

找原因:个人直觉,定位到@Scope注解,源码如下:


属性中value和scopeName是一样的,由@AliasFor得知。ConfigurableBeanFactory.SCOPE_PROTOTYPE="prototype"所以我上面没写错。那看最后一个属性proxyMode,指定代理类型。还有


红色区域内,不会产生代理除非定义的类型不同与default。

看看ScopedProxyMode里都有什么?如下:


原来default=no,而interfaces为接口代理,也就是jdk代理,target_class为类代理。

恍然大明白,修改自己的代码如下:


运行:


结果:perfect!

分享一个坑,也有解决问题的思路。

如果哪里有误,或者有其他建议,不用保留!!!

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,185评论 19 139
  • 文章作者:Tyan博客:noahsnail.com 3.5 Bean scopes When you create...
    SnailTyan阅读 1,944评论 0 1
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,993评论 6 342
  • 自从进了和君,开始知道了王阳明其人,但是没有看相关的书籍,对王阳明的了解也不够。最近我开始研读第一本关于王阳明的著...
    刘永扬阅读 688评论 0 0
  • 遇见是缘分 某一天 再见却是注定 再见那一年的遇见 不美好的遇见,那将是美妙的邂逅 或许,再见是为了彼此更好的遇见...
    强哥哥biubiu阅读 280评论 0 1