Java 依赖注入EJB 3-选择太多?

Java 依赖注入EJB 3-选择太多?,java,spring,dependency-injection,ejb,cdi,Java,Spring,Dependency Injection,Ejb,Cdi,我们正在启动一个基于EJB3.0的新项目。我有一个基于“spring”的背景(我很喜欢),所以对我来说,松散耦合和可测试性是一个必须具备的重要条件。这篇文章不应该是关于“ejb与spring”的。这将是完美的,如果你已经有了与此相关的实际项目经验 下面是一些示例代码来演示该问题: 客户端->ejb->协作者1->协作者..->合作者 <!-- language: java --> @Stateless public class SampleService { // or @

我们正在启动一个基于EJB3.0的新项目。我有一个基于“spring”的背景(我很喜欢),所以对我来说,松散耦合和可测试性是一个必须具备的重要条件。这篇文章不应该是关于“ejb与spring”的。这将是完美的,如果你已经有了与此相关的实际项目经验

下面是一些示例代码来演示该问题:

客户端->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) {
        // ...
    }
}

@无国籍
公共类示例服务{
//或通过CDI注入
//或通过弹簧自动接线
@EJB//或通过EJB3.0使用无状态会话bean
私人银行;
//这个组件也是一样的
@EJB
私人计算器;
//两个协作者都必须可以从外部设置,以使一切都可以测试(和模拟)
/**
*从客户端调用的“业务服务”示例
*/
公共作废借方(大小数金额){
计算(金额减去(新的大十进制(100));
银行借方(金额);
}
}
//或者通过@Component(Spring)或CDI?
@无状态//或带有可选@Service/@Singleton注释的无状态会话bean?
公共类计算器{
公共无效计算(BigDecimal减法){
//计算东西。。。。
}
}
//或者通过@Component(Spring)或CDI?
@无状态//或带有可选@Service/@Singleton注释的无状态会话bean?
公营银行{
公共作废借方(大小数金额){
// ...
}
}
我想知道在EJB3.0中为所有协作者及其协作者实现依赖注入的最佳方法是什么?从这个意义上讲,协作者可以是非常非常小的专用类

到目前为止,我们已经讨论了以下选项,但仍然没有得出正确的结论:)

  • 只使用ejb标准,所有内容都是无状态会话bean和所有后果(如池、资源处理等)

  • 使用无状态会话bean作为“业务组件”(入口点)并从此开始

  • a) spring有线依赖项(通过“jboss snowdrop”集成)

    b) CDI有线依赖项(通过针对ejb 3.0和jboss eap 5.1的WELD)

    我不需要知道如何在单元测试中使用bean。我想要的答案是,连接正在运行的appserver内部所有依赖项的最佳方法是什么(spring vs.guice vs.CDI vs.EJB)。我只需要知道从外部EJB(“业务入口点”)向下的图形。因此,外部的一切(servlet、前端等)都不是这个问题的范围:)

    请假设为项目设置了EJB 3.0和jboss eap 5.1:)


    期待您的回答,希望您能学到一些基于项目的知识。

    一般来说,在Java中有“太多的选择”,因此在这方面也肯定会有。我不会将EJB描述为一个通用的依赖注入框架,相反,它们使用DI来实现自己的目的。如果这就是您想要编码的方式,那么您应该考虑为此添加一个框架。如果你知道并且喜欢春天,那就去吧。如果您还需要另一个框架来解决如何做到这一点,我已经将Guice与EJB结合使用(这是一本很好的烹饪书)也取得了很好的效果。

    如果您的主要目标是允许在测试中使用依赖项注入,我建议您只通过将这些值更改为受保护或提供设置程序来设置这些值。我非常喜欢使用Mockito来存根Java EE EJB3.0中的所有内容,并且在进行集成测试之外的任何测试时,只允许Mockito为我存根方法,但是如果您正在寻找完全依赖项注入,比如基于同一类拥有多个不同bean的功能,但是,对于不同的依赖关系,我会推荐,正如Yishai所说的,最好使用Spring。

    如果您需要方法级事务管理、安全性、并发管理或会话bean可以提供的任何其他服务,那么就让它们成为EJB会话bean。您可以从托管bean开始,然后在需要时让它们成为会话bean

    如果要将这些会话bean注入托管bean(在CDI中,托管bean是jar文件中的任何内容,该jar文件包含meta inf目录中的beans.xml文件),则使用@EJB。如果要将普通托管bean注入会话bean,请使用@inject

    如果您想要注入远程会话bean(或任何JavaEE远程资源),那么这个链接解释了如何通过适配器类来实现这一点。本质上,它将所有用于查找等的讨厌字符串保留在一个地方,然后允许您像对待任何其他可注入bean一样对待这些远程资源(通过适配器成员变量上的@products注释)。您不必这样做,但建议您这样做


    我绝对会投票反对混合框架。 我正在从事一个项目,该项目连接EJB、Spring和JBossSeam(还有一半Flex,一半JSF前端)。一个真正的科技动物园
    无论如何,将所有这些连接在一起并不是最糟糕的部分,这些框架具有灵活的注入功能。测试或多或少也是可以忍受的。
    最痛苦的是消除由不同生命周期模型引起的内存泄漏、同步事务和清理线程行为。 现在我们转向纯JavaEE6(摆脱Spring、Flex并从Seam转向CDI)。到目前为止,我们对结果非常满意。
    顺便说一句,我不是在批评春天。坚持使用Java EE或Spring stack,混用它们只是自找麻烦。

    那么,在您的上下文中,什么是协作者呢?谢谢您的回答。是的,主要是测试用的。我很好奇是否有人说“是的,每个bean(协作者)都可以是无状态会话bean”,或者有人说“不要混合这些框架”等等。我还听到有人说“让一切都成为一个无状态会话bean。容器是为池、资源处理等而设计的。不要只使用像spring或guice这样的DI框架——这还为时过早。”