相干 EJB3,无状态会话Bean 与 Spring 依赖注入 Singleton 的困惑
有关 EJB3,无状态会话Bean 与 Spring 依赖注入 Singleton 的困惑!
最近我在学习 EJB3。关于它的无状态会话Bean,我有一些困惑。
按照 EJB3 规范,容器会为每一种无状态会话 Bean 创建一定数量的实例,然后将它们保存在一个缓冲池(pool) 里面,然后根据调用的情况,将它们在调用者之间分配。书上特别强调了,因为这些 bean 都是无状态的,所以自由度很高。比如说,一个对象调用了无状态会话 Bean 的方法A,执行了一段时间;然后,又调用了同一个 Bean 的方法B。但实际上,它调用的是实例 1 的方法A,和实例 2 的方法B。只不过这一切,对调用者来说都是透明的。
这就是我的困惑所在。我们都知道,可以用无状态的 Singleton 来封装一些领域服务。比如说,UserService,就可以是一个 Singleton class。在实际使用时,可以用 IoC 容器的依赖注入方法得到它的一个(全 JVM 唯一的)Singleton 实例,然后再调用它里面的方法,比如说:
一切都很基础。
我现在主要的问题就是,EJB 容器为无状态会话 Bean 创建多个实例并缓冲,到底有什么特别的好处?既然他们是无状态的,为什么不可以整个系统共享一个实例呢?难道说,多个实例的执行效率更高?这似乎颠覆了我个人的 JVM 基本概念.....
请各位指教。谢谢。
但是,sleep的含义是令 当前 thread 进入睡眠状态啊。
比如,我的一个对象 I 在一个 thread 里面调用了 userService 的方法 A,但因为某种原因,执行了方法 A 中的 Thread.sleep(xxx) 语句。与此同时,另一个对象 II 在另一个 thread 里面也试图调用 userService 的方法 A。我认为,这时候,对象 II 的调用不会被阻挡,因为 UserService 类是无状态的,方法 A 也就不是 synchronized 的。
所以,这样看来,无状态 bean 似乎确实不需要对象池来缓冲.....Singleton 就好了...
哦,谢谢。这和我的困惑有点类似,就是无状态bean的对象池似乎没有必要。Singleton 就好了。
哈哈,初级会员嘛,夸张在所难免。
我个人的 JVM 基本概念,就是 JVM 会(在不同线程中)同时执行一个对象的非 synchronized 方法的多个拷贝,不需要任何额外的等待时间。
基于这个概念,我认为,使用无状态的 singleton 类来当 XyzService,是最佳的选择,不会有任何效率上的不良影响。
也因此,我不明白 EJB 为无状态 session bean 提供对象池的意义何在。当然,我以前没有做过 EJB 1, 2 的项目,所以对其历史不了解。希望资深的各位大侠不吝赐教!
哈哈,初级会员嘛,夸张在所难免。
我个人的 JVM 基本概念,就是 JVM 会(在不同线程中)同时执行一个对象的非 synchronized 方法的多个拷贝,不需要任何额外的等待时间。
基于这个概念,我认为,使用无状态的 singleton 类来当 XyzService,是最佳的选择,不会有任何效率上的不良影响。
也因此,我不明白 EJB 为无状态 session bean 提供对象池的意义何在。当然,我以前没有做过 EJB 1, 2 的项目,所以对其历史不了解。希望资深的各位大侠不吝赐教!一说倒还真是的,以前只知道有一个线程池的概念,但是为什么需要它不是很清楚!
对,我也认为,调用端会随机的访问不同的bean实例。
但我不认为这样效率会更高些。否则的话,Spring 也应该隐含的为那些 service bean 提供缓冲池,而不是简单的用 singleton 来解决问题。
其实,对于有状态 bean,我还是理所当然的认为对象池可以提高效率的,因为1,系统确确实实需要有状态 bean 的多个实例(就因为他们是有状态的);2,创建一个 bean 的开销可能很大。
但对于无状态 bean,我的疑问继续成立
这就是我的困惑所在。我们都知道,可以用无状态的 Singleton 来封装一些领域服务。比如说,UserService,就可以是一个 Singleton class。在实际使用时,可以用 IoC 容器的依赖注入方法得到它的一个(全 JVM 唯一的)Singleton 实例,然后再调用它里面的方法,比如说:
Singleton 并不是这样的吧 他只是在 servletcontext里面保存了这么一份 beans
每个request过来的时候,使用的是threadlocal
threadlocal 可以说是“拷贝”了 servletcontext里面的beans
可以说是一个副本
这样可以保证多个request使用的beans互相不影响(具体可以理解一下threadlocal )
threadlocal 的实现本身就类似 对象池 ,不过这个东西是语言支持的,而不是自己来实现的。
你说的synchronize 在一般bean上都不会起作用,原理也是这样 用的根本不是同一个对象(当然static得注意),除非在同一个request中存在多次调用产生 synchronize 现象。
无状态Sb本身就是借助对象池来体现“无状态”,如果没有Pool,则创建出来的对象必然有状态,只是在于是否被捕获并且表现出来。我个人觉得无状态sb用内存换速度,一定程度上减少创建对象的开销,但是现在内存不值钱,而且对象池的稳定性的确让人忧虑,本人写的大多数对象池都问题多多!
多谢资深发言指教。还要多问一句,“无状态SessionBean确实没有必要搞对象池”,其原因是不是就是我提出的那个呢?
Singleton 并不是这样的吧 他只是在 servletcontext里面保存了这么一份 beans
每个request过来的时候,使用的是threadlocal
threadlocal 可以说是“拷贝”了 servletcontext里面的beans
可以说是一个副本
这样可以保证多个request使用的beans互相不影响(具体可以理解一下threadlocal )
threadlocal 的实现本身就类似 对象池 ,不过这个东西是语言支持的,而不是自己来实现的。
你说的synchronize 在一般bean上都不会起作用,原理也是这样 用的根本不是同一个对象(当然static得注意),除非在同一个request中存在多次调用产生 synchronize 现象。
我一向认为,Spring对于(缺省状态下为Singleton模式的)Bean,都是在整个 JVM 里面保持唯一一个实例的。
可能是我一直以来都搞错了吧。因为我没有真正去仔细了解Spring对 Singleton Bean 是如何提供支持的。
无状态Sb本身就是借助对象池来体现“无状态”,如果没有Pool,则创建出来的对象必然有状态,只是在于是否被捕获并且表现出来。我个人觉得无状态sb用内存换速度,一定程度上减少创建对象的开销,但是现在内存不值钱,而且对象池的稳定性的确让人忧虑,本人写的大多数对象池都问题多多!
我不这样认为。相反,我觉得:
1,应根据其具体需要来确定一个bean是否有状态;
2,有状态bean需要对象池,因为我们肯定会同时需要多个有状态bean,所以保持一个池可以提高效率;
3,无状态bean不需要对象池,JVM 唯一的 singleton 就可以了,并不会增加任何开销。
请问,你所说的,是 Spring 的做法吗?
而且,在缺省条件下,不是整个 JVM 只有一个 ClassLoader 吗?
最近我在学习 EJB3。关于它的无状态会话Bean,我有一些困惑。
按照 EJB3 规范,容器会为每一种无状态会话 Bean 创建一定数量的实例,然后将它们保存在一个缓冲池(pool) 里面,然后根据调用的情况,将它们在调用者之间分配。书上特别强调了,因为这些 bean 都是无状态的,所以自由度很高。比如说,一个对象调用了无状态会话 Bean 的方法A,执行了一段时间;然后,又调用了同一个 Bean 的方法B。但实际上,它调用的是实例 1 的方法A,和实例 2 的方法B。只不过这一切,对调用者来说都是透明的。
这就是我的困惑所在。我们都知道,可以用无状态的 Singleton 来封装一些领域服务。比如说,UserService,就可以是一个 Singleton class。在实际使用时,可以用 IoC 容器的依赖注入方法得到它的一个(全 JVM 唯一的)Singleton 实例,然后再调用它里面的方法,比如说:
public class ... { private UserService userService; public void setUserService(UserService v) { // IoC 容器将会注入 UserService 的一个实现的实例, // 这也将是整个 JVM 共享的一个实例。 userService = v; } ... public boolean isValidUser(String username, String password) { User user = userService.processLogin(username, password); return (user != null); } }
一切都很基础。
我现在主要的问题就是,EJB 容器为无状态会话 Bean 创建多个实例并缓冲,到底有什么特别的好处?既然他们是无状态的,为什么不可以整个系统共享一个实例呢?难道说,多个实例的执行效率更高?这似乎颠覆了我个人的 JVM 基本概念.....
请各位指教。谢谢。
1 楼
dennis_zane
2007-02-06
对象池是对早期JVM性能上的妥协,现在的存在意义值的怀疑
2 楼
抛出异常的爱
2007-02-06
dennis_zane 写道
对象池是对早期JVM性能上的妥协,现在的存在意义值的怀疑
如果对象中需要sleep(c/s中会有用)没有池那大家只能等着
3 楼
非典型程序员
2007-02-06
抛出异常的爱 写道
dennis_zane 写道
对象池是对早期JVM性能上的妥协,现在的存在意义值的怀疑
如果对象中需要sleep(c/s中会有用)没有池那大家只能等着但是,sleep的含义是令 当前 thread 进入睡眠状态啊。
比如,我的一个对象 I 在一个 thread 里面调用了 userService 的方法 A,但因为某种原因,执行了方法 A 中的 Thread.sleep(xxx) 语句。与此同时,另一个对象 II 在另一个 thread 里面也试图调用 userService 的方法 A。我认为,这时候,对象 II 的调用不会被阻挡,因为 UserService 类是无状态的,方法 A 也就不是 synchronized 的。
所以,这样看来,无状态 bean 似乎确实不需要对象池来缓冲.....Singleton 就好了...
4 楼
非典型程序员
2007-02-06
dennis_zane 写道
对象池是对早期JVM性能上的妥协,现在的存在意义值的怀疑
哦,谢谢。这和我的困惑有点类似,就是无状态bean的对象池似乎没有必要。Singleton 就好了。
5 楼
ahuaxuan
2007-02-06
ejb3.0最终没有能颠覆它原来的线程模型,其中缘由不是三言两语能够说清楚的,但是
引用
这似乎颠覆了我个人的 JVM 基本概念
似乎太夸张了吧。
6 楼
非典型程序员
2007-02-06
ahuaxuan 写道
ejb3.0最终没有能颠覆它原来的线程模型,其中缘由不是三言两语能够说清楚的,但是
引用
这似乎颠覆了我个人的 JVM 基本概念
似乎太夸张了吧。哈哈,初级会员嘛,夸张在所难免。
我个人的 JVM 基本概念,就是 JVM 会(在不同线程中)同时执行一个对象的非 synchronized 方法的多个拷贝,不需要任何额外的等待时间。
基于这个概念,我认为,使用无状态的 singleton 类来当 XyzService,是最佳的选择,不会有任何效率上的不良影响。
也因此,我不明白 EJB 为无状态 session bean 提供对象池的意义何在。当然,我以前没有做过 EJB 1, 2 的项目,所以对其历史不了解。希望资深的各位大侠不吝赐教!
7 楼
jamesby
2007-02-06
非典型程序员 写道
ahuaxuan 写道
ejb3.0最终没有能颠覆它原来的线程模型,其中缘由不是三言两语能够说清楚的,但是
引用
这似乎颠覆了我个人的 JVM 基本概念
似乎太夸张了吧。哈哈,初级会员嘛,夸张在所难免。
我个人的 JVM 基本概念,就是 JVM 会(在不同线程中)同时执行一个对象的非 synchronized 方法的多个拷贝,不需要任何额外的等待时间。
基于这个概念,我认为,使用无状态的 singleton 类来当 XyzService,是最佳的选择,不会有任何效率上的不良影响。
也因此,我不明白 EJB 为无状态 session bean 提供对象池的意义何在。当然,我以前没有做过 EJB 1, 2 的项目,所以对其历史不了解。希望资深的各位大侠不吝赐教!
8 楼
jamesby
2007-02-06
Stateless Session Bean设计池的概念应该是不同的调用端同一时间访问的一定不是同一个Bean实例!
9 楼
非典型程序员
2007-02-06
jamesby 写道
Stateless Session Bean设计池的概念应该是不同的调用端同一时间访问的一定不是同一个Bean实例!
对,我也认为,调用端会随机的访问不同的bean实例。
但我不认为这样效率会更高些。否则的话,Spring 也应该隐含的为那些 service bean 提供缓冲池,而不是简单的用 singleton 来解决问题。
10 楼
jamesby
2007-02-06
servlet是线程池实现的典型,ejb是对象池实现的典型,至于对象池有哪些好处?搞不清楚,不知道它为什么会提高性能?
11 楼
非典型程序员
2007-02-06
jamesby 写道
servlet是线程池实现的典型,ejb是对象池实现的典型,至于对象池有哪些好处?搞不清楚,不知道它为什么会提高性能?
其实,对于有状态 bean,我还是理所当然的认为对象池可以提高效率的,因为1,系统确确实实需要有状态 bean 的多个实例(就因为他们是有状态的);2,创建一个 bean 的开销可能很大。
但对于无状态 bean,我的疑问继续成立
12 楼
robbin
2007-02-06
无状态SessionBean确实没有必要搞对象池,这一点Rod Johnson在《without EJB》里面有很详细的论述。
13 楼
jianfeng008cn
2007-02-06
引用
这就是我的困惑所在。我们都知道,可以用无状态的 Singleton 来封装一些领域服务。比如说,UserService,就可以是一个 Singleton class。在实际使用时,可以用 IoC 容器的依赖注入方法得到它的一个(全 JVM 唯一的)Singleton 实例,然后再调用它里面的方法,比如说:
Singleton 并不是这样的吧 他只是在 servletcontext里面保存了这么一份 beans
每个request过来的时候,使用的是threadlocal
threadlocal 可以说是“拷贝”了 servletcontext里面的beans
可以说是一个副本
这样可以保证多个request使用的beans互相不影响(具体可以理解一下threadlocal )
threadlocal 的实现本身就类似 对象池 ,不过这个东西是语言支持的,而不是自己来实现的。
你说的synchronize 在一般bean上都不会起作用,原理也是这样 用的根本不是同一个对象(当然static得注意),除非在同一个request中存在多次调用产生 synchronize 现象。
引用
(全 JVM 唯一的)Singleton 实例
是否你的理解出偏差了呢?
14 楼
retreat
2007-02-06
robbin 写道
无状态SessionBean确实没有必要搞对象池,这一点Rod Johnson在《without EJB》里面有很详细的论述。
无状态Sb本身就是借助对象池来体现“无状态”,如果没有Pool,则创建出来的对象必然有状态,只是在于是否被捕获并且表现出来。我个人觉得无状态sb用内存换速度,一定程度上减少创建对象的开销,但是现在内存不值钱,而且对象池的稳定性的确让人忧虑,本人写的大多数对象池都问题多多!
15 楼
jamesby
2007-02-07
(全 JVM 唯一的)Singleton 实例肯定是不对的,准确地说应该是一个ClassLoader一个实例,当然,父ClassLoader 已经load了一个实例,则子不需要Load实例
16 楼
非典型程序员
2007-02-07
robbin 写道
无状态SessionBean确实没有必要搞对象池,这一点Rod Johnson在《without EJB》里面有很详细的论述。
多谢资深发言指教。还要多问一句,“无状态SessionBean确实没有必要搞对象池”,其原因是不是就是我提出的那个呢?
17 楼
非典型程序员
2007-02-07
jianfeng008cn 写道
Singleton 并不是这样的吧 他只是在 servletcontext里面保存了这么一份 beans
每个request过来的时候,使用的是threadlocal
threadlocal 可以说是“拷贝”了 servletcontext里面的beans
可以说是一个副本
这样可以保证多个request使用的beans互相不影响(具体可以理解一下threadlocal )
threadlocal 的实现本身就类似 对象池 ,不过这个东西是语言支持的,而不是自己来实现的。
你说的synchronize 在一般bean上都不会起作用,原理也是这样 用的根本不是同一个对象(当然static得注意),除非在同一个request中存在多次调用产生 synchronize 现象。
引用
(全 JVM 唯一的)Singleton 实例
是否你的理解出偏差了呢?我一向认为,Spring对于(缺省状态下为Singleton模式的)Bean,都是在整个 JVM 里面保持唯一一个实例的。
可能是我一直以来都搞错了吧。因为我没有真正去仔细了解Spring对 Singleton Bean 是如何提供支持的。
18 楼
非典型程序员
2007-02-07
retreat 写道
robbin 写道
无状态SessionBean确实没有必要搞对象池,这一点Rod Johnson在《without EJB》里面有很详细的论述。
无状态Sb本身就是借助对象池来体现“无状态”,如果没有Pool,则创建出来的对象必然有状态,只是在于是否被捕获并且表现出来。我个人觉得无状态sb用内存换速度,一定程度上减少创建对象的开销,但是现在内存不值钱,而且对象池的稳定性的确让人忧虑,本人写的大多数对象池都问题多多!
我不这样认为。相反,我觉得:
1,应根据其具体需要来确定一个bean是否有状态;
2,有状态bean需要对象池,因为我们肯定会同时需要多个有状态bean,所以保持一个池可以提高效率;
3,无状态bean不需要对象池,JVM 唯一的 singleton 就可以了,并不会增加任何开销。
19 楼
非典型程序员
2007-02-07
jamesby 写道
(全 JVM 唯一的)Singleton 实例肯定是不对的,准确地说应该是一个ClassLoader一个实例,当然,父ClassLoader 已经load了一个实例,则子不需要Load实例
请问,你所说的,是 Spring 的做法吗?
而且,在缺省条件下,不是整个 JVM 只有一个 ClassLoader 吗?