解决Spring中singleton的Bean依赖于prototype的Bean的问题
来源:互联网 发布:mac 查看系统运行程序 编辑:程序博客网 时间:2024/05/16 11:12
scope="prototype"没写的问题,项目中对一个表的增删该操作是用一个action,这个actionadd,update,delete,save这些方法, 添加和修改是共用一个页面,当页面得到id时代表进行的修改操作,反之是添加操作。因为在配置spring的bean是忘了写scope="prototype" 所以每次添加时都显示最后一次访问过的记录,scope="prototype" 会在该类型的对象被请求 时创建一个新的action对象。如果没有配置scope=prototype则添加的时候不会新建一个action,他任然会保留上次访问的过记录的信息 webwork的Action不是线程安全的,要求在多线程环境下必须是一个线程对应一个独立的实例,不能使用singleton。所以,我们在Spring配置Webwork Action Bean时,需要加上属性scope=”prototype”或singleton=”false”。
singleton模式指的是对某个对象的完全共享,包括代码空间和数据空间,说白了,如果一个类是singleton的,假如这个类有成员变量,那么这个成员变量的值是各个线程共享的(有点类似于static的样子了),当线程A往给变量赋了一个值以后,线程B就能读出这个值。因此,对于前台Action,肯定不能使用singleton的模式,必须是一个线程请求对应一个独立的实例。推而广之,只要是带数据成员变量的类,为了防止多个线程混用数据,就不能使用singleton。对于我们用到的Service、Dao,之所以用了singleton,就是因为他们没有用到数据成员变量,如果谁的Service需要数据成员变量,请设置singleton=false。 有状态的bean都使用Prototype作用域,而对无状态的bean则应该使用singleton作用域。
另外,当Spring容器中作用域不同的Bean相互依赖时,可能出现一些问题,例如:一个作用域为Singleton的Bean(设为A)依赖于一个作用域为prototype的Bean(设为B)。由于A是单例的,只有一次初始化的机会,它的依赖关系也只在初始化阶段被设置,但它所依赖的B每次都会创建一个全新的实例,这将使A中的B不能及时得到更新。这样将导致如果客户端多次请求A,并调用A中B的某个方法(或获取A中B的某个属性),服务端总是返回同一个B,但客户端直接请求B却能获得最新的对象,这就产生了对象不同步的情况。这样就违背了B初衷:本来希望B具有prototype的行为,但是却表现出singleton的行为了。那么,问题如何解决呢?
办法有二:
部分放弃依赖注入:当A每次需要B时,主动向容器请求新的Bean实例,即可保证每次注入的B都是最新的实例。
利用方法注入。
第一种方式显然不是一个好的做法,代码主动请求Bean实例,必然导致代码与SpringAPI耦合在一起,造成严重的代码污染。通常情况下,我们会采用第二种做法。使用方法注入。
方法注入通常使用lookup方法注入,利用lookup方法注入可以让Spring容器重写容器中Bean的抽象或具体方法,返回查找容器中其他Bean的结果,被查找的Bean通常是一个non-singleton的Bean(尽管也可以是一个singleton的Bean)。Spring通过使用CGLIB库修改客户端的二进制码,从而实现上述要求。看下面的例子:
上面的CellPhone将被部署成prototype的Bean,并被一个singleton的Bean所依赖。如果让Spring容器直接将prototype的Bean注入到singleton中,就会出现上面的问题。为了解决这个问题,我们在singleton的Bean里增加一个抽象方法,该方法的返回类型是一个被依赖的Bean——注意这个方法是一个抽象方法,因为程序中没有为该方法提供实现,这个实现过程由Spring完成。下面是该singleton作用域的Bean的代码:
上面的代码定义了一个抽象的getPhone方法,通常情况下,程序不能调用这个方法,但Spring框架将会负责为该方法提供是先提,这样这个方法就会变成具体方法了,程序也就可以调用该方法了。为了让Spring知道如何实现该方法,我们需要在配置文件中使用<lookup-method>标签,这个标签需要指定如下两个属性:
name:指定需要让Spring实现的方法
bean:指定Spring实现该方法后返回的值
下面是配置片段:
上面配置的<lookup-method>指定Spring将负责实现getPhone方法,该方法将返回容器中的prototype类型的cellPhone实例。下面是测试类:
执行结果如下:
结果表明:当lookup方法注入后,系统每次调用getPhone都会返回最新的CellPhone实例而非最早的CellPhone实例。
注意:要保证lookup方法注入每次产生的Bean实例,必须将目标Bean(本例为cellPhone)布署成prototype作用域。否则,如果容器中只有一个目标Bean实例,即使采用lookup方法注入,每次依然返回同一个Bean实例。另外,lookup方法注入不仅能用于设值注入,还能用于构造注入。
- 转--解决Spring中singleton的Bean依赖于prototype的Bean的问题
- 解决Spring中singleton的Bean依赖于prototype的Bean的问题
- 解决Spring中singleton的Bean依赖于prototype的Bean的问题
- 解决Spring中singleton中注入prototype Bean的问题
- Spring中Bean的作用域singleton, prototype
- 《转》详解Spring中bean的scope singleton prototype request...
- 解决singleton Bean依赖prototype Bean不能实时更新的问题
- Spring 受管理 Bean scope 的 prototype 和 singleton 区别
- spring bean scope=prototype/singleton的差别
- Spring源码学习之bean的prototype和singleton类型
- spring创建bean模式singleton与prototype的区别
- spring Bean的作用域(singleton&prototype)
- spring prototype的每个对象中中创建singleton的bean
- Spring中Bean的scope的singleton和prototype使用场景
- Spring 中 bean 的作用域:singleton;prototype;WEB 环境作用域
- Spring容器中Bean的作用域之singleton和prototype
- Spring的Bean-singleton模式
- Spring学习笔记 关于Spring创建Bean的模式-Singleton(单例模式)和Prototype
- chm页面无法显示
- matlab、1
- Hibernate之缓存详解
- The Best Path ----HDU
- 关于Java反射机制中的Field简单尝试与示例以及说明
- 解决Spring中singleton的Bean依赖于prototype的Bean的问题
- 算法期中——合并二叉树
- Android Studio提升开发效率小技巧
- jQuery基础
- Python time模块
- 数据结构-位图(可对海量数据进行处理)
- php.ini配置
- Oracle数据库对象的逻辑、物理、内存结构
- main方法