依赖注入 EJB 3 - 选择太多?
我们正在启动一个基于 EJB 3.0 的新项目。我有一个基于“spring”的背景(并且喜欢它),所以对我来说松散耦合和可测试性是一个很大的必须。这篇文章不应该是关于“ejb 与 spring”的。如果您已经有这方面的实际项目经验,那就完美了。
这是一些示例代码来演示该问题:
client -> ejb->合作者 1 ->合作者..->协作者
<!-- language: java -->
@Stateless
public class SampleService {
// or @Inject via CDI
// or @Autowired via Spring
@EJB // or just use a stateless session bean via EJB 3.0
private Bank bank;
// same for this component
@EJB
private Calculator calc;
// both collaborators must be settable from outside, to make everything testable (and mockable)
/**
* sample "business service" called from client
*/
public void debit(BigDecimal amount){
calc.calculate(amount.subtract(new BigDecimal(100)));
bank.debit(amount);
}
}
// or via @Component (Spring), or CDI?
@Stateless // or Stateless Session bean with optional @Service/@Singleton annotation?
public class Calculator {
public void calculate(BigDecimal subtract) {
// calculate stuff....
}
}
// or via @Component (Spring), or CDI?
@Stateless // or Stateless Session bean with optional @Service/@Singleton annotation?
public class Bank {
public void debit(BigDecimal amount) {
// ...
}
}
我想知道在 ejb 3.0 中为所有协作者及其协作者实现依赖注入的最佳方法是什么?从这个意义上讲,合作者可以是非常非常小的专门班级。
到目前为止,我们已经讨论了以下选项,但始终没有得出正确的结论:)
仅使用 ejb 标准,所有内容都是无状态会话 bean 以及所有后果(如池、资源处理等)< /p>
使用无状态会话 bean 作为“业务组件”(入口点)并从此开始
a) spring 有线依赖项(通过“jboss Snowdrop”集成)
b) CDI 有线依赖项(通过 ejb 3.0 和 jboss eap 5.1 的 WELD)
我不不需要知道如何在单元测试中使用 bean。我想要的答案是什么是连接正在运行的应用程序服务器内的所有依赖项的最佳方法(spring、guice、CDI、EJB)。我只需要知道从外部 EJB(“业务入口点”)向下的图表。因此,外部的所有内容(servlet、前端等)不是这个问题的范围:)
请假设 EJB 3.0 和 jboss eap 5.1 已为该项目设置:)
期待您的答案并希望有一些项目基础知识。
We are starting a new project based on EJB 3.0. I have a "spring" based background (and love it), so for me loose coupling and testability is a big must have. This post should not be about "ejb vs. spring". It would be perfect if you already have real project experience with this.
here is some example code to demonstrate the problem:
client -> ejb -> collaborator 1 -> collaborator .. -> collaborator n
<!-- language: java -->
@Stateless
public class SampleService {
// or @Inject via CDI
// or @Autowired via Spring
@EJB // or just use a stateless session bean via EJB 3.0
private Bank bank;
// same for this component
@EJB
private Calculator calc;
// both collaborators must be settable from outside, to make everything testable (and mockable)
/**
* sample "business service" called from client
*/
public void debit(BigDecimal amount){
calc.calculate(amount.subtract(new BigDecimal(100)));
bank.debit(amount);
}
}
// or via @Component (Spring), or CDI?
@Stateless // or Stateless Session bean with optional @Service/@Singleton annotation?
public class Calculator {
public void calculate(BigDecimal subtract) {
// calculate stuff....
}
}
// or via @Component (Spring), or CDI?
@Stateless // or Stateless Session bean with optional @Service/@Singleton annotation?
public class Bank {
public void debit(BigDecimal amount) {
// ...
}
}
i want to know what is the best way to implement dependency injection for all the collaborators and their collaborators in ejb 3.0? collaborators in this sense can be very very small dedicated classes.
we have discussed the the following options so far and like always don't have a proper conclusion yet :)
only use the ejb standard with everything beeing a stateless session bean and all consequences (like pooling, resource handling etc.)
use stateless session beans as "business components" (entry points) and from there on
a) spring wired dependencies (via "jboss snowdrop" integration)
b) CDI wired dependencies (via WELD for ejb 3.0 and jboss eap 5.1)
i don't need to know how i can use the beans in a unit test. the answer i am after is what is the best approach to wire up all the dependencies inside the running appserver (spring vs. guice vs. CDI vs. EJB). i only need to know the graph from the outer EJB ("business entry point") downwards. so everything outside (servlets, frontend etc.) is not scope of this question :)
please, assume EJB 3.0 and jboss eap 5.1 are set for the project :)
looking forward to your answers and hopefully some project based knowledge.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果您需要方法级事务管理、安全性、并发管理或会话 Bean 可以提供的任何其他服务,那么请将它们设为 EJB 会话 Bean。您可以从托管 Bean 开始,然后在需要时将它们设为会话 Bean。
如果您想将这些会话 bean 注入到托管 bean 中(在 CDI 中,托管 bean 是包含 meta-inf 目录中的 beans.xml 文件的 jar 文件中的任何内容),则使用 @EJB。如果您想将普通托管 Bean 注入到会话 Bean 中,请使用 @Inject。
如果您想注入远程会话 bean(或任何 Java EE 远程资源),则此链接解释了如何通过适配器类来执行此操作。本质上,它将所有用于查找等的讨厌字符串保留在一个位置,然后允许您像任何其他可注入 bean 一样处理这些远程资源(通过适配器成员变量上的 @Produces 注释)。您不必这样做,但建议您这样做。
类型安全资源注入
If you need method level transaction management, security, concurrency management or any other services that a session bean can offer then make them EJB session beans. You can start out with managed beans and then make them session beans as and when you need to.
If you want to inject these session beans into managed beans (which in CDI is anything in a jar file that contains a beans.xml file in the meta-inf directory) then use @EJB. If you want to inject a plain managed bean into a session bean use @Inject.
If you want to inject remote session beans (or any Java EE remote resource) then this link explains how you can do this via an adapter class. Essentially it keeps all of your nasty strings for lookups etc in one place and allows you then to treat these remote resources just like any other injectable bean (via the @Produces annotation on the adapter member variables). You don't have to do this but it is recommended.
Typesafe resource injection
我肯定会投票反对混合框架。
我正在开发一个与 EJB、Spring 和 JBoss Seam 挂钩的项目(并且还有半 Flex、半 JSF 前端)。真正的科技动物园!
无论如何,将它们连接在一起并不是最糟糕的部分,这些框架具有灵活的注入功能。测试也或多或少是可以忍受的。
最痛苦的是摆脱不同生命周期模型导致的内存泄漏、同步事务、清理线程行为。
现在我们正在转向纯 Java EE 6(摆脱 Spring、Flex 并从 Seam 转向 CDI)。到目前为止,我们对结果非常满意。
顺便说一句,我并不是在批评 Spring。坚持使用 Java EE 或 Spring 堆栈,混合它们只会带来麻烦。
I would definitely vote against mixing frameworks.
I'm working on a project that is hooked on EJB, Spring and JBoss Seam (and also has half-Flex, half-JSF front-end). A true technology zoo!
Anyway, wiring it all together is not the worst part, those frameworks have flexible injection capabilities. Testing is also more or less bearable.
The most painful was to get rid of memory leaks caused by different lifecylce models, synchronize transaction, and clean up threading behavior.
Now we're moving to pure Java EE 6 (getting rid of Spring, Flex and shifting from Seam to CDI). So far we're really pleased with the results.
BTW, I'm not criticizing Spring. Stick with either Java EE or Spring stack, mixing them is just asking for trouble.
一般来说,Java 有“太多的选择”,所以在这个领域也是如此。我不会将 EJB 描述为通用的依赖注入框架,而是它们使用 DI 来实现其目的。如果这就是您想要的编码方式,您应该为此目的添加一个框架。如果你了解并喜欢Spring,那就去吧。我已将 Guice 与 EJB 一起使用(此处 是一本很好的食谱),如果您需要另一个框架来弄清楚如何做到这一点,效果也很好。
Well in general in Java there are "too many choices," so certainly in this area as well. I would not describe EJB as a general purpose Dependency Injection framework, rather they use DI for their purposes. If that is how you want to code, you should look to add a framework for this purpose. If you know and like Spring, go for it. I have used Guice with EJB's (here is a nice cookbook) to good effect as well, if you needed yet another framework to figure out how to do this.
如果您的主要目标是允许依赖注入进行测试,我建议您通过将这些值更改为受保护或为它们提供设置器来设置这些值。我喜欢使用 Mockito 来存根 Java EE EJB 3.0 中的所有内容,并且在进行集成测试之外的任何测试时,只允许 Mockito 为我存根方法,但是如果您正在寻找完整的依赖项注入,例如具有以下功能:几个不同的 bean 基于同一个类,但具有不同的依赖关系,我会像 Yishai 所说的那样推荐,并在上面使用 Spring。
If your main goal is to allow dependency injection for testing I would recommend just letting those values be settable via changing them to protected or giving them setters. I'm a fan of using Mockito to stub everything in Java EE EJB 3.0 and when doing any testing outside of integration testing to just allow Mockito to stub the methods for me, but if you are looking for full dependency injection like the capability to have several different beans based off of the same class, but with different dependencies I would recommend as Yishai said and going with Spring on top.