【问题标题】:Dependency injection and container class (java-ee 7)依赖注入和容器类(java-ee 7)
【发布时间】:2017-04-04 10:39:36
【问题描述】:

我是 DI 新手,但突然需要在我的 EJB 应用程序中使用它,所以我尝试重新制作它。

该方法包括具有 2 个字段的容器类 - 2 个实现。它可以根据参数与一个或两个实现一起使用。该容器是在单例的方法调用中创建的,但由其他 ejb bean 使用。

这里我需要帮助 - 如何使 SecurityContainer 类与其他 CDI 托管类(ejb bean)正常工作或成为 CDI 托管类?

我给出了一个旧的(非 CDI)代码,它是如何工作的。读取参数并实例化容器:

@Singleton
public class MySingleton {
    private static final MySingleton instance = new MySingleton();
    private volatile SecurityHelper securityHelper;  // container
    public void setSecurityHelper(SecurityHelper secHelper){ securityHelper=secHelper; }
    public SecurityHelper getSecurityHelper(){ return securityHelper; }     
    /* now it has some @Inject....*/    

    public void start(String passwordP, String passwordH)
          .....
        // application work with one or two implementations of security
        if ("P".equals(DbParams.getServerSecurityFlag()))
            instance.setSecurityHelper(new SecurityContainer(new SecurityHelperImplP(DbWorkerImpl.getInstance(), ResponseBuilderImpl.getInstance()), 
                                null));             
        else 
            instance.setSecurityHelper( new SecurityContainer( new SecurityHelperImplP(DbWorkerImpl.getInstance(), ResponseBuilderImpl.getInstance()), 
                                new SecurityHelperImplH(DbWorkerImpl.getInstance(), ResponseBuilderImpl.getInstance()) ) );
        securityHelper.createSecurity(passwordP, passwordH);

这里是容器类:

public class SecurityContainer implements SecurityHelper {
    private SecurityHelper secPrg;
    private SecurityHelper secHard;
    public SecurityContainer(SecurityHelper secPrg, SecurityHelper secHard){
        this.secPrg=secPrg;
        this.secHard=secHard;
    }

具体实现现在必须注入 DbWorker 和 ResponseBuilder ejb bean。 SecurityHelperImplH 看起来一样。

public class SecurityHelperImplP implements SecurityHelper {
    private SecurityPrg securityPrg = null;

    private DbWorker ora;           // now they are CDI managed
    private ResponseBuilder builder; 

    public SecurityHelperImplP(DbWorker dbworker, ResponseBuilder bld){
        this.ora = dbworker;
        this.builder = bld;
    }

我认为我需要资格赛,也许还需要一名制片人,但无法将这些点联系起来

【问题讨论】:

    标签: java containers cdi java-ee-7 inject


    【解决方案1】:

    从外观上看,你可以选择任何一种方式 - 生产者或限定符。两者都需要一些重构,对我来说,生产者似乎是一种更顺畅的方式。 它将允许您检查参数并根据您的需要定制生产者对象 (SecurityContainer)。

    首先,你SecurityContainer的字段需要是注入点,所以加上@Inject

    @Inject
    private volatile SecurityHelper securityHelper;  // container
    

    注意:请记住删除 setter 方法,使用 CDI 时,您不需要/不需要它。

    现在谈谈我们如何生产它。你的开始工作基本上已经完成了!您所需要的只是使其成为生产者,设置正确的返回类型并确保您获得适当的参数。所以,一步一步来:

    1) 生产者方法参数

    生产者方法的所有参数都被自动视为另一个可注入源。例如。您将能够@Inject String passwordP)。哎呀,这不会马上起作用,我不知道你是如何准确检索这些参数的。

    2) producer 方法如何操作

    这是 CDI 每次调用的方法,它需要创建一个实例。所以你必须对SecurityHelper的范围下定决心。由于这是在 @Singleton 的启动方法中设置一次,我想这是在运行时不会改变的东西。在这种情况下,您可能需要@ApplicationScoped

    3) 那么这一切看起来如何?

    假设我没有误解,这是一个应该做你想做的代码:

    @Produces  // telling CDI this is how it is supposed to create instances of this type
    @ApplicationScoped // what scope does the produced bean have?
    public SecurityHelper produceSecHelper() {
      // TODO add logic to retrieve these params!
      String passwordP;
      String passwordH;
    
      SecurityHelper result;
      // application work with one or two implementations of security
      if ("P".equals(DbParams.getServerSecurityFlag()){
          result = new SecurityContainer(new SecurityHelperImplP(DbWorkerImpl.getInstance(), ResponseBuilderImpl.getInstance()), 
                                    null); 
      } else {
          result = new SecurityContainer( new SecurityHelperImplP(DbWorkerImpl.getInstance(), ResponseBuilderImpl.getInstance()), 
                                    new SecurityHelperImplH(DbWorkerImpl.getInstance(), ResponseBuilderImpl.getInstance()));
      }
      result.createSecurity(passwordP, passwordH);
      return result;
    }
    

    注意:CDI 将自行调用此方法。您不应该手动执行此操作,即使您这样做,CDI 也不会识别它。

    【讨论】:

    • 你想把这个制作人放在哪里?现在我离开了SecurityContainer。 MySingleton 现在由 CDI 托管,其他托管 bean 使用来自 mySingleton getSecurityHelper() 的 securityContainer。
    • 没关系,只要生产者驻留在另一个 CDI bean 中(以便 CDI 能够找到它)。来自 CDI 1.2 规范 - A producer method must be a default-access, public, protected or private, non-abstract method of a managed bean class or session bean class. 所以我说,把它放在你方便的地方。
    • 我是否应该将 SecurityHelperImplP 和 SecurityHelperImplH 作为参数传递给生产者?我试图通过限定符传递它们,但得到编译错误
    • 如果你想将它们作为参数,你需要为两者都有一个生产者,带有限定符,因为它们都是相同的类型(字符串)。我想你有他们。我不知道你遇到了什么编译错误。但是由于它是编译,你做错了什么,你的 IDE 通常会告诉你什么。
    猜你喜欢
    • 2012-11-11
    • 2014-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-30
    相关资源
    最近更新 更多