Scope
这一节我们就来说说Scope到底有多少种,我们最熟悉的就是singleton和prototype, 也可能许多人认为只有这两种,其实不是,除了这两个还有三个,分别是request,session,application。这三个是web领域的作用域。前两种想必大家已经很熟悉了,我们这里只讲后三种。
首先对这三种分别做个简单的说明,request作用域,意思就是每一次请求就会创建一个新的Bean对象,请求结束就会销毁,再次请求又会创建新的。 session作用域,也就是不同的会话也会创建不同的Bean,当会话超时或者程序关闭,Bean对象也会被销毁。Application作用域,也就是整个应用程序。只有程序重启时会重新创建新的Bean,应该可以看作是一个变相的单例吧。
接下来说明下测试的环境代码,启动类就是最基本的。在编写三个Bean,作用域分别为上面的三种,并实现DisposableBean接口,实现销毁方法。最后就是定义一个controller类,我们这里为什么要加入@Lazy这个注解呢,后面再讲,现在只需要知道需要加上该注解就可以。
测试环境准备已经做好了,现在可以开始做测试了。这是第一次请求时的对象,当我们发送第二次请求时可以看到只有request变换了,session和application并没有变化,我们再到控制台看看,是否执行了销毁方法,发现也执行了。
接下来看看session,请求不同不能改变session的bean,所以我们用另外个浏览器进行访问。发现bean确实不同,session的销毁是关闭程序或者等待超时,我们这里就直接关闭程序了。这里可能同学就有疑惑,为什么application的销毁方法没执行,嘿嘿,具体我也不清楚。差不多就这样吧。反正了解了解,重要的还是singleton和prototype
Scope失效解决方法
我们现在准备进行测试的大致流程就是,当一个单例对象中,注入多例对象时,每次取出的对象是否是同一个。下面就是测试环境准备。启动类没什么变化,我们通过拿到Bean1 并多次调用getBean2方法。分别定义了Bean1,和Bean2,Bean1就是单例,Bean2是多例,Bean1将会依赖注入Bean2。
我们预期的就是当程序启动,三次输出将会是不同的对象,但事与愿违,三次对象都是一样的。为什么呢,原因也是比较简单,@Autowired注解的依赖注入只会执行一次,也就是Bean1在被创建的时候,会执行。之后无论调用多少次方法,bean2都将会是最开始注入的那一个对象。
解决办法1(@Lazy注解)
我们可以在注入的属性上加入@Lazy注解,当我们加上@Lazy注解后,就不是单纯的注入Bean2对象了,此时注入的就是Bean2的代理对象,当我们使用到该属性时,才会到容器中找到符合条件的对象,这里的对象是多例,所以就会重复创建新对象。
解决办法2(ObjectFactory<>)
也可以不用代理对象,我们这里也可以用对象工厂,对象工厂也可以识别到对象的多例,给我们返回不同的对象。泛型要写我们需要用到的Bean。通过getObject方法进行获取。
解决方法3(ApplicationContext)
这一种最简便,也是最好理解,我们都知道,多例对象的创建,只有在使用时会进行创建,他不像单例对象一来就创建好了。所以我们用ApplicationContext的getBean方法,每次调用,返回的对象也将会不一样。
推荐不要使用代理对象的方法,就是用后两种就可以。代理对象比较耗性能。
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 4 天,点击查看活动详情















