[读书笔记] EJB 3 in Action: Spring Bean 与 EJB Session Bean 的异同
用了一段时间 Spring, 看了一下 Guice, 现在开始看 EJB 了。书选的是 EJB 3 in Action , 现在只看到第三章。测试服务器用的是 JBOSS 5.1, 用 MyEclipse 开发。
Spring Container 里面的对象功能类似于 EJB 3 中的无状态会话Bean(SLSB), 或者更类似于 EJB 3.1 引入的 Singleton。尽管绝大部分业务逻辑都能用 spring 完美解决, 但 EJB 3 一些特有的功能能给我们提供一些新的思路。
- SLSB 无须考虑并发。 首先是 SLSB, 由于有 poll 的概念, 所以同一时间只有一个 SLSB 只有一个客户端在访问, 所以在编程时不必考虑并发. 但如果要在运行期修改参数就比较麻烦了, EJB 3.1 可以用 Singleton 来解决, EJB 3 用什么? @Resource 可以用来解决这个问题么? 如果可以解决的话会不会有效率问题。
- SFSB 给你新的选择。 对于有状态会话Bean(SFSB), 在 Spring 中没有对应的概念。靠近 web 端的需求一般用 HttpSession 来解决, 而靠近后端的一般就用 memcache 来解决了(有时候也用数据库, 或者在内存中用 Map 来储存数据), 有的时候直接把状态储存在对象中, 每次调用时把状态对象作为参数传入, 就把一个 SFSB 转成一个 SLSB 了。比较之下, 用 SFSB 来解决 类似的问题能更干净一些, 但书中也多次强调 SFSB 的风险, 特别是忘记 @Remove 时内存方面会出问题 。
- EJB 容器支持更好的延迟加载。 尽管Spring Bean 容器支持延迟加载, 但能用上的机会不多, 因为只有树顶的 Bean 能支持延迟加载, 同时对于 web 工程, 树顶基本都是 Controller, 而 Controller 在 URL 映射绑定阶段基本就全部加载完毕了。当然, 你也可以让你的类实现 ApplicationContextAware/BeanFactoryAware, 然后注入 Bean 的名字而不是 Bean 本身来实现延迟加载, 不过这样实在是太麻烦了; 有观点认为不应当使用延迟加载, 因为启动时就发现资源不存在或者资源不足, 比起运行期再发现会好很多。
EJB 容器支持更好的延迟加载, 当你调用一个 EJB 时, 并不需要初始化他所依赖的 EJB, 他依赖的这些 EJB 可能不存在, 也可能在 EJB Container 的缓冲池中, 甚至可能在远端, 只有当调用被依赖的 EJB 上的方法时, 才需要初始化一个或者从池中取一个。 EJB 容器对内存不足有一些防范措施, 比如可以销毁 SLSB, 持久化甚至销毁 SFSB 。而对于其他资源(如数据库), JBOSS 一般使用独立的部署文件(比如 *-ds.xml), 这些资源不存在时, 启动阶段就会有警告。 - EJB Container 是全局的。 由于种种原因(比如人员协调,比如测试服务器启动太慢), 我们会把一个应用拆分到多个 webapp 上, 每个 webapp 上面一个 spring container。这样带来了一些问题, 比如需要更小心的处理一致性问题; 单例类被创建了多个, 浪费了资源; 运行期变更状态时需要通知多个webapp等等。EJB Container 是在 application server 级别的, 所以很多问题很自然地消失了。
- 可以从客户端访问EJB。 在后台写界面来控制所有的运行参数实在是太麻烦了, 特别是运行参数经常增 删的情况下。 所以我们的做法是把需要配置的类通过 MBean 来暴露, 通过 JMX 接口来管理。不过比较起来, 声明一个 EJB @Remote 接口, 比声明 MBean 看起来干净多了。@WebService 也许是一个更好的主意, 不过现在还没看到, 不敢确定。 spring-ws 还没看过, 不知道是否适合用来解决这个问题。
Spring 现在能完美地支持我的工作内容, 所以我也不会考虑马上就倒向 EJB, 我只是不想做井底之蛙而已。
欢迎指正。