CDI传递服务的最佳方式

时间:2018-03-28 08:35:47

标签: java java-ee cdi

我有几个这样的服务:

@Singleton
public SimpleService {
    ...
}

我有Managed Bean @ViewScoped,它应该创建一些复杂的对象。这些对象应该执行业务逻辑。我需要将这些服务传递给这个对象。

Managed Bean示例:

@ManagedBean
@ViewScoped
public class ExampleBean {
    @Inject
    private SimpleService simpleService;

    ...
    public void customLogic() {
        // in this method I should create complex object which should have services and some data.
        // current implementation
        ComplexObject object = new ComplexObject(SimpleService simpleService, ...)
    }
}

通过@Inject批注将服务注入Managed Bean。为了创建这些对象 - 我正在使用构造函数并将这些服务作为参数传递。问题是:我可以在构造函数中传递服务吗?

2 个答案:

答案 0 :(得分:3)

你可以:

  • 按方法注入:
    private MyService myService;

    @Inject
    public void setMyService(MyService ms) {
        this.myService = ms;
    }
  • 按字段注入:
    @Inject
    private MyService myService;   
  • 通过 List<StorageAccount> accounts = azure.storageAccounts().list(); for (StorageAccount sa : accounts) { System.out.println("Storage Account " + sa.name() + " created @ " + sa.creationTime()); } 获取引用(不推荐,高级用例除外):
    ...
    MyService myService = CDI.current().select(MyService.class).get();
    ...
  • 通过CDI获取引用(不推荐,高级用例或CDI 1.0除外):
    ...
    BeanManager beanManager = CDI.getBeanManager(); // you can fetch a BeanManager reference by several other methods, I use CDI for simplicity here
    MyService myService = beanManager.getReference(MyService.class);
    ...
  • 如果您的BeanManager注释是@Singleton而不是javax.ejb.Singleton,那么您的bean实际上是一个EJB,您还可以使用任何允许您访问EJB的机制,例如{{ 1}}注释,或通过JNDI上下文。

我个人倾向于通过方法注入,因为我发现它在大多数时候是最灵活的选择。在我看来,它也是对其他框架最“可移植”的(例如:Spring)

请记住,当您使用javax.inject.Singleton@Resource方法获取CDI.current() bean时,您有责任手动销毁获取的bean已完成,所以你不会落入this CDI-related memory leak。使用BeanManager时,就像保存@Dependent引用并在之后调用它一样简单:

CDI.current()

Instance方法太低级,只能在CDI 1.0环境中使用(当... Instance<MyService> msInstance = CDI.current().select(MyService.class); MyService myService = msInstance.get(); ... msInstance.destroy(myService); ... 类尚不存在时)。您可以阅读链接的StackOverflow问题以获取更多详细信息。

答案 1 :(得分:2)

你在做什么都很好。您正在使用ManagedBean作为桥接来注入服务,然后将注入的变量传递给需要服务的ComplexObject。

应该考虑的唯一限制是,ComplexObject类本身可以是ManagedBean吗?这样你可以直接在它上面注入所有内容,但如果不可能,你可以使用bean。

我更喜欢提到的按字段注入选项,因为我认为它更具可读性。