如何使serviceloader创建类处理容器管理对象

时间:2013-08-21 13:40:50

标签: jsf dependency-injection cdi serviceloader

我正在编写一个库,我希望我的库用户实现一个接口。从我的库中我称之为实现。

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

现在我遇到了一个问题。我正在创建一个展示我正在使用自己的库的展示。这是一个web应用程序,我正在使用jsf和CDI。当我从我的库中实例化所述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将始终为null ...这意味着没有人使用DI容器可以使用我的库。我知道我可以通过FacesContext查找获取managedbean并获取managedbean但更重要的是,如果你考虑它,我的库设计得不是很好。

总结我的问题: 有什么方法可以让serviceloader使用DI容器来实例化类?

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

任何知道更好的方法来获取我需要的东西而不让集成商实现接口但是我可以从集成商那里获得信息的人?

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

提前致谢

1 个答案:

答案 0 :(得分:0)

由于未在CDI容器内执行Example的实现,因此不会发生注入。你可以做的是使用BeanManager手动查找bean。根据{{​​3}},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 是您要查找的依赖项。