Java 在自定义范围中使用注入

Java 在自定义范围中使用注入,java,scope,cdi,weld,custom-scope,Java,Scope,Cdi,Weld,Custom Scope,是否可以在自定义范围的上下文中将@SessionScopedbean用作字段 我正在用CDI编写一个自定义范围(“ScreenScoped”),这样它的行为与CDI的@ViewScoped(我这样做是因为后者与WebSphere不兼容)。到目前为止,我的范围就像@ApplicationScoped一样。我想使用我的@SessionScoped NavigationHandler类来确定屏幕范围的生命周期何时结束,该类在用户每次单击链接或按钮时都被称为。但是,当我尝试使用@Injected字段时,

是否可以在自定义范围的上下文中将
@SessionScoped
bean用作字段

我正在用CDI编写一个自定义范围(“ScreenScoped”),这样它的行为与CDI的
@ViewScoped
(我这样做是因为后者与WebSphere不兼容)。到目前为止,我的范围就像
@ApplicationScoped
一样。我想使用我的
@SessionScoped NavigationHandler
类来确定屏幕范围的生命周期何时结束,该类在用户每次单击链接或按钮时都被称为。但是,当我尝试使用
@Inject
ed字段时,确实会出现错误

public class ScreenContext
    implements Context
{
    @Inject
    private NavigationHandler navigationHandler;
    ...
}
由于此
@Inject
,出现NullPointerException:

16:55:07,492 SEVERE [javax.enterprise.resource.webcontainer.jsf.application] (http-localhost/127.0.0.1:8443-10) Error Rendering View[/page/hello.xhtml]: javax.el.ELException: /page/hello.xhtml @24,58 visible="#{helloController.popupshowed}": java.lang.NullPointerException

...

Caused by: java.lang.NullPointerException
    at com.mypackage.scope.screenscope.ScreenContext.get(ScreenContext.java:38) [myproject.jar:]
第38行是我第一次调用注入字段:

System.out.println("Navigation is used: " + navigationHandler.getUserId());

不能在
上下文中注入Bean。您需要使用
BeanManager
来访问
NavigationHandler
bean

您的上下文是通过CDI扩展在CDI生命周期的
AfterBeanDiscovery
事件中注册的。在这里,您可以将
BeanManager
传递给上下文:

public void afterBeanDiscovery (@Observes final AfterBeanDiscovery event, final BeanManager beanManager)
{
    event.addContext(new ScreenContext(beanManager));
}
然后在您的
ScreenContext
实现中,您可以使用
BeanManager
获取
NavigationHandler
bean(在下面的
myMethod
中):

public class ScreenContext implements Context
{

   private final BeanManager m_beanManager;

   public ScreenContext(final BeanManager p_BeanManager)
   {
      m_beanManager = p_BeanManager;
   }

   public void myMethod()
   {
      NavigationHandler NavigationHandlerBean = getNavigationHandler();
      ...
      ...
   }

   private NavigationHandler getNavigationHandler()
   {
      final Set<Bean<?>> beans = m_beanManager.getBeans(NavigationHandler.class);
      final Bean<?> bean = m_beanManager.resolve(beans);

      return (NavigationHandler) m_beanManager.getReference(bean, NavigationHandler.class, m_beanManager.createCreationalContext(bean));
   }
公共类ScreenContext实现上下文
{
私有最终BeanManager m_BeanManager;
公共屏幕上下文(最终BeanManager p_BeanManager)
{
m_beanManager=p_beanManager;
}
公共方法()
{
NavigationHandler NavigationHandlerBean=getNavigationHandler();
...
...
}
私有NavigationHandler getNavigationHandler()
{
final Set bean=m_beanManager.resolve(bean);
return(NavigationHandler)m_beanManager.getReference(bean,NavigationHandler.class,m_beanManager.createCreationContext(bean));
}

使用BeanManager获取NavigationHandler Bean因为自定义上下文是通过扩展注册的,无法执行注入测试后,我发现即使NavigationHandler是WindowScoped,从两个不同的浏览器调用时,该方法始终返回同一个对象。我重新接受了您的答案,因为我的评论是由于另一个原因在以下帖子中解决的er问题:如果这对您有帮助,我很高兴:-)