PAX-CDI:CdiContainerFactory 和 BundleTracker
PAX-CDI: CdiContainerFactory and BundleTracker
我使用 felix 和 pax-cdi 0.13 进行焊接。我在 B 中有两个包 A。在包 A 中,我有 BundleTracker 和 Customizer,在包 B 中,我有 CDI bean。所以我想在 bundle tracker 中使用 bean 管理器从 bundle B 中获取 cdi bean。所以我在定制器中有方法:
@Override
public Object addingBundle(Bundle bundle, BundleEvent event) {
String marker = (String) bundle.getHeaders().get("Some-Marker");
if (marker != null) {
try {
//1 we get CdiContainerFactory
BundleContext thisBundleContext=FrameworkUtil.getBundle(this.getClass()).getBundleContext();
ServiceReference<?> sr = thisBundleContext.getServiceReference(CdiContainerFactory.class.getName());
CdiContainerFactory cdiContainerFactory = (CdiContainerFactory) thisBundleContext.getService(sr);
if (cdiContainerFactory==null){
System.out.println("Cdi container factory is null");
}else{
System.out.println("Cdi container factory is not null");
}
//2 we get BeanManager from CdiContainerFactory
Class<?> klass = bundle.loadClass("com.temp.Temp");
BeanManager beanManager = cdiContainerFactory.getContainer(bundle).getBeanManager();
Bean<?> bean = (Bean<?>)beanManager.resolve(beanManager.getBeans(klass));
Object temp= beanManager.getReference(bean, bean.getBeanClass(), beanManager.createCreationalContext(bean));
} catch (ClassNotFoundException ex) {
Logger.getLogger(ExtenderBundleTracker.class.getName()).log(Level.SEVERE, null, ex);
}
}
return bundle;
}
要注册捆绑跟踪器,我使用以下代码:
bundleTracker=new BundleTracker<>(context, Bundle.ACTIVE, new MyCustomizer());
上面的代码有效。但不总是。我有时间问题。我总是得到 Cdi container factory is not null
,但下面一行
BeanManager beanManager = cdiContainerFactory.getContainer(bundle).getBeanManager();
有时会抛出 NullPointerException。
正如我所想的那样,当 Bundle B 变为活动状态时,CDI 容器仍未准备好。这样的问题怎么解决?
有时找不到 bean 管理器是因为 CDI 容器也是由来自 PAX-CDI 包的包侦听器(异步地)创建的。这意味着您可能 运行 进入竞争状态,因为容器可能会或可能不会在您的捆绑侦听器被调用时创建。
使用 PAX-CDI 时,我不建议尝试访问 bean 管理器,而是将您需要的 bean 导出为 OSGi 服务(bean 上的@OsgiServiceProvider 注释)并通过 ServiceTracker
。如果由于 bean 的范围而无法做到这一点,您始终可以在容器中创建一个单独的工厂模式 bean 来为您完成 bean 创建工作并将该 bean 作为服务导出。
我使用 felix 和 pax-cdi 0.13 进行焊接。我在 B 中有两个包 A。在包 A 中,我有 BundleTracker 和 Customizer,在包 B 中,我有 CDI bean。所以我想在 bundle tracker 中使用 bean 管理器从 bundle B 中获取 cdi bean。所以我在定制器中有方法:
@Override
public Object addingBundle(Bundle bundle, BundleEvent event) {
String marker = (String) bundle.getHeaders().get("Some-Marker");
if (marker != null) {
try {
//1 we get CdiContainerFactory
BundleContext thisBundleContext=FrameworkUtil.getBundle(this.getClass()).getBundleContext();
ServiceReference<?> sr = thisBundleContext.getServiceReference(CdiContainerFactory.class.getName());
CdiContainerFactory cdiContainerFactory = (CdiContainerFactory) thisBundleContext.getService(sr);
if (cdiContainerFactory==null){
System.out.println("Cdi container factory is null");
}else{
System.out.println("Cdi container factory is not null");
}
//2 we get BeanManager from CdiContainerFactory
Class<?> klass = bundle.loadClass("com.temp.Temp");
BeanManager beanManager = cdiContainerFactory.getContainer(bundle).getBeanManager();
Bean<?> bean = (Bean<?>)beanManager.resolve(beanManager.getBeans(klass));
Object temp= beanManager.getReference(bean, bean.getBeanClass(), beanManager.createCreationalContext(bean));
} catch (ClassNotFoundException ex) {
Logger.getLogger(ExtenderBundleTracker.class.getName()).log(Level.SEVERE, null, ex);
}
}
return bundle;
}
要注册捆绑跟踪器,我使用以下代码:
bundleTracker=new BundleTracker<>(context, Bundle.ACTIVE, new MyCustomizer());
上面的代码有效。但不总是。我有时间问题。我总是得到 Cdi container factory is not null
,但下面一行
BeanManager beanManager = cdiContainerFactory.getContainer(bundle).getBeanManager();
有时会抛出 NullPointerException。 正如我所想的那样,当 Bundle B 变为活动状态时,CDI 容器仍未准备好。这样的问题怎么解决?
有时找不到 bean 管理器是因为 CDI 容器也是由来自 PAX-CDI 包的包侦听器(异步地)创建的。这意味着您可能 运行 进入竞争状态,因为容器可能会或可能不会在您的捆绑侦听器被调用时创建。
使用 PAX-CDI 时,我不建议尝试访问 bean 管理器,而是将您需要的 bean 导出为 OSGi 服务(bean 上的@OsgiServiceProvider 注释)并通过 ServiceTracker
。如果由于 bean 的范围而无法做到这一点,您始终可以在容器中创建一个单独的工厂模式 bean 来为您完成 bean 创建工作并将该 bean 作为服务导出。