2

我想编写一个 CDI 扩展,它从数据库加载一些实体(实际上是实现某个接口的 groovy 脚本)并将它们作为 bean 提供,这样就可以获得由 CDI 注入的该接口的所有实现。我想…… 如下所示:

public class ExtensionClass implements Extension {
  @Inject 
  EntityManager em;

  public void afterBeanDiscovery(@Observes final AfterBeanDiscovery event, final BeanManager manager) {
    Entity entity = em.find();
    //do sth with entity...
  }
}

当我尝试以这种方式注入实体管理器时,它为空(这并不让我感到惊讶,我没想到 @Inject 可以在 CDI 扩展类中工作)。

是否可以通过某种方式(例如通过 BeanManager)访问 CDI 扩展中的实体管理器?还是我必须以其他方式访问数据库?

4

2 回答 2

1

您必须为 EntityManager 创建一个生产者。但是,我不建议在扩展中执行它,它不是可移植的(它可能适用于所有实现,但这将是那些灰色区域之一)。还需要生成实体,而不是让 CDI 容器处理它。如果您需要在应用程序开始时对实体执行某些操作,我建议您使用@StartupEJB 规范。

于 2013-05-11T16:23:54.117 回答
0

如果有人对如何在 CDI 扩展中获取实体管理器感兴趣,我就是这样做的。首先,正如 LightGuard 所说,您必须创建一个生产者以使实体管理器可用:

 @Produces
 @MyQualifier
 public javax.persistence.EntityManager create() {
   return entityManager;
 }

在 cdi 扩展中,您可以执行以下操作:

 public class ScriptingExtension implements Extension {
   public void afterBeanDiscovery(@Observes final AfterBeanDiscovery event, final BeanManager manager) {
     final Set<Bean<?>> embeans = manager.getBeans(EntityManager.class);
     final Bean<?> bean = manager.resolve(embeans);

     final CreationalContext<?> creationalContext = manager.createCreationalContext(bean);
     final EntityManager em = (EntityManager) manager.getReference(bean, EntityManager.class, creationalContext);
     //do sth with entity manager... 
    }
  }

请注意,在这种情况下,实体管理器仅在容器 CDI 生命周期的这一点可用,而不是更早的时候可用(例如在 ProcessAnnotatedType 中)。就我而言,这是一个问题,因为我想否决一些 bean,为此我不得不提前拦截。所以我选择使用对数据源的直接 JNDI 查找来加载与我相关的信息……。像这样:

final InitialContext ctx = new InitialContext();
final DataSource dataSource = (DataSource) ctx.lookup("java:/jdbc/myDatasource");
于 2013-05-17T10:30:17.247 回答