Java EE CDI - 生成带有注入(inject)字段的 bean

标签 java jakarta-ee cdi

因为我有一些泛型需要传递给新生成的对象,所以我正在创建一个生产者。但是,当生产者工作时,EntityManager 不会被注入(inject),因为生产者使用运算符 new 创建实例,而不是使用 CDI。

如何生成支持 CDI 的对象?

代码:

预选赛:

@Qualifier
@Retention(RUNTIME)
@Target(
{ FIELD, TYPE, METHOD })
public @interface Multiselector
{
   Class<? extends Dbo> clazz();
}

制作人:

@SessionScoped
public class MultiselectorProducer implements Serializable
{

   @Produces
   @Multiselector(clazz = SpecialDbo.class)
   public MultiselectorService<SpecialDbo> produce()
   {
       return  new MultiselectorService<SpecialDbo>(SpecialDbo.class);
   }

}

服务等级:

@Stateful
@LocalBean
public class MultiselectorService<T extends Dbo> implements Serializable
{

    @Inject
    private EntityManager em;

    private List<T>     itemList;

    public MultiselectorService()
    {
    }

    public MultiselectorService(Class<? extends Dbo> clazz)
    {
       itemList = em.createQuery("some Sql String", clazz);
    }

    ....
}

注意:EntityManager 是一个自定义的 CRUD 服务,否则可以正确注入(inject)

欢迎对代码提出任何改进建议。谢谢!

最佳答案

你混合了很多不相关的东西:

  1. 您的服务MultiselectorService是一个 EJB,并且您不能使用生产者来生产它。创建应用程序后,EJB 就会注册,然后根据它创建实例的范围。

  2. 你有一个方法public void MultiselectorService(Class<? extends Dbo> clazz)其名称与构造函数类似,违反惯例。

  3. 假设您已将该方法固定为构造函数,但随后行 'itemList = em.createQuery("some Sql String", clazz);'会因 NPE 失败。因为em仅在 bean 创建后才会初始化。有两种方法可以做到这一点:

    • 将实体管理器注入(inject)到构造函数中(如果您仍将使用 EJB,这违反了 EJB 规范)

    • 在带有注解“@PostConstruct”的方法中执行初始化操作

  4. 你有 EntityManager 的制作人吗? ?例如您不能只注入(inject)实体管理器,您需要提供 EJB 资源,并带有注释 @PersistenceContext

我理解您想要实现的目标。主要问题是手动创建的 bean 不受容器管理,这意味着拦截器和装饰器将不适用(例如 PostConstruct 和 Transactional 注释将不起作用)。检查here 。到目前为止,实现这一目标的最佳方法是:

  public interface SpecialDboMultiselectorService extends MultiselectorService {


  }

  @Stateless
  public class SpecialDboMultiselectorServiceImpl extends MultiselectorServiceImpl<SpecialDbo> implements SpecialDboMultiselectorService
  {

        public SpecialDboMultiselectorServiceImpl() {
             super(SpecialDbo.class);
        }
  }


  public class MultiselectorServiceImpl<T extends Dbo> implements MultiselectorService {

     @Inject  
     private EntityManager em;

     private Class<? extends Dbo> clazz;

     private List<T> itemList;

     public MultiselectorService(Class<? extends Dbo> clazz) {
         this.clazz = clazz
     }

     @PostConstruct
     public void init() {
        itemList = em.createQuery("some Sql String", clazz);
     }
  }

并注入(inject)SpecialDboMultiselectorService .

关于Java EE CDI - 生成带有注入(inject)字段的 bean,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27147760/

相关文章:

java - 如何使用硬编码的 html 页面发送 servlet 响应?

java - 如何调用远程java类(方法)

jsf - Glassfish 3.1.1 上的 OpenJPA 2.1.1 增强问题

java - 在非托管 CDI Bean 中引用 CDI Bean

java - 我的角色扮演游戏中静态最终对象的滥用是什么?

java - 将 XML 文件发送到单独的应用程序; JSP 还是 Servlet? JAVA

jsf-2 - 将资源注入(inject) UIComponent(也就是 CDI 在这里工作吗?)

cxf - TomEE + CXF配置引用

java - AppEngine Java 重新索引任务/映射器/作业

java - 在 Spring 中访问计划任务