【问题标题】:How to make a serviceloader created class handle container managed objects如何使服务加载器创建的类处理容器管理的对象
【发布时间】:2023-04-08 14:05:01
【问题描述】:

我目前正在编写一个库,我希望我的库的用户在其中实现一个接口。在我的库中,我调用了这个实现。

我正在使用 ServiceLoader 来实例化集成商提供的实现,它工作得很好。集成器在我的库中调用 start() 方法,最后他得到了一些回报。该实现用于为我提供一些我需要的东西,以便获得最终结果。 (我故意不使用 CDI 或任何其他 DI 容器,因为我想创建一个可以在任何地方使用的库。在桌面应用程序中,spring 应用程序是使用 guice 的应用程序......)

现在我面临一个问题。我正在创建一个使用我自己的库的展示。这是我使用 jsf 和 CDI 的 web 应用程序。当我从我的库中实例化所述 webapp 中提供的实现时,我正在处理一个非容器托管对象。但是由于这个实现需要使用容器管理的对象,我有点搞砸了,因为这永远无法工作。

示例: lib中的接口:

public interface Example{
   public abstract String getInfo();
}

战争中的实施:

public class ExampleImpl implements Example{

   @Inject
   private ManagedBean bean;
   public String getInfo(){
      return bean.getSomethingThatReturnsString();
   }
}

正如您所见,这是我的库构建方式中的一个大问题,因为 bean 将始终为空......这意味着使用 DI 容器的任何人都无法使用我的库。我知道我可以通过查找 FacesContext 并获取 managedbean 来获取 managedbean,但更重要的是,如果你仔细想想,我的库设计得不是很好。

所以结束我的问题: 有什么办法可以让服务加载器使用 DI 容器来实例化类?

谁知道解决我问题的更好方法?

谁知道更好的方法来获得我需要的东西而不让集成器实现接口但我可以从集成器获取信息?

我知道这是一个非常抽象的问题,但我有点卡在这个问题上。

提前致谢

【问题讨论】:

    标签: jsf dependency-injection cdi serviceloader


    【解决方案1】:

    由于示例的实现不在 CDI 容器内执行,因此不会发生注入。您可以做的是使用 BeanManager 手动查找 bean。根据docs,BeanManager 绑定到jndi 名称java:comp/BeanManager。使用以下代码,您可以在实现类中获取 BeanManager 并手动查找依赖项:

    InitialContext context = new InitialContext();
    BeanManager beanManager = (BeanManager) context.lookup("java:comp/BeanManager");
    Set<Bean<?>> beans = beanManager.getBeans(YourBean.class, new AnnotationLiteral<Default>() {});
    Bean<YourBean> provider = (Bean<YourBean>) beans.iterator().next();
    CreationalContext<YourBean> cc = beanManager.createCreationalContext(provider);
    YourBean yourBean = (YourBean) beanManager.getReference(provider, YourBean.class, cc);
    

    YourBean 是您要查找的依赖项。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-03-09
      • 2014-02-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-22
      相关资源
      最近更新 更多