【问题标题】:dependency injection (CDI) in java EE 8java EE 8 中的依赖注入 (CDI)
【发布时间】:2018-06-07 17:52:49
【问题描述】:

我一直在研究 CDI 以简化代码,并且我一直在尝试将它与 Java EE 8 一起使用。我试图复制现有示例但没有成功。我想知道是否有人可能遇到过同样的问题:

PoolManager 类:

import javax.ejb.Startup;
import javax.ejb.Singleton;
import javax.annotation.PostConstruct;

@Singleton
@Startup
public class PoolManager {

    private Queue<Object> pooledObjects;

    @PostConstruct
    private void init() {
        System.out.println("Hi");
        pooledObjects = new LinkedBlockingQueue<Object>(1_000);
        for (int i = 0; i <= 1000; i++) {
            pooledObjects.offer(i);
        }   
    }


    public void returnObject(Object o) {
        pooledObjects.offer(o);
    }

    public Object borrowObject() {
        return pooledObjects.poll();
    }
}

UsePoolManager 类:

public class UsePoolManager {

    @Inject 
    private PoolManager poolManager;

    public void usePooledObject() {
        Object object = this.poolManager.borrowObject();
        System.out.println(object);
    }

}

和主要的:

public static void main(String[] args) {

        UsePoolManager user = new UsePoolManager();
        user.usePooledObject();
    }
}

注入似乎在运行时根本不起作用。我没有bean xml(我知道这没有必要,添加它并没有改变任何东西。)。

任何帮助将不胜感激。

谢谢!


检查我是使用 SE 还是 EE 进行澄清...

【问题讨论】:

  • 我猜你是说 CDI。
  • 你是怎么运行这个的?你说 EE 8,然后有一个main()。
  • 使用 jre.1.8.0_141 - 在 Eclipse 中使用 Main 调试 - 我已经使用 java 几个月了,不是专家,但我安装了 EE 版本.. - 我还在 gradle 中添加了如果有帮助,请使用以下依赖项..: // mvnrepository.com/artifact/javax.inject/javax.inject compile group: 'javax.inject', name: 'javax.inject', version: '1' // mvnrepository.com/artifact/javax.ejb/javax.ejb-api compile group: 'javax.ejb',名称:'javax.ejb-api',版本:'3.2.2'
  • 我确实使用的是 SE 而不是 EE。感谢您的澄清!

标签: java jakarta-ee cdi


【解决方案1】:

您需要在 JBoss 或 Tomcat 等 JavaEE 容器中运行它,而不是像独立的 JavaSE 应用程序(使用 publis static void main)

【讨论】:

  • 谢谢安东尼奥斯。我也在看 CDI 2 以防万一。是不是一个不错的选择。目前不确定我是否想迁移到 EE,但我喜欢在 EE 中处理模式的方式……如果这是个坏主意,请告诉我。否则,我将简要介绍一下我对 CDI 2 的体验这里是为了争论...谢谢大家!
  • Tomcat != JavaEE。尝试像 arquillian 这样的测试框架
【解决方案2】:

为了论证,使用 Java SE 的 CDI 2 容器:

在 Gradle 中:

// https://mvnrepository.com/artifact/org.jboss.weld.se/weld-se-core
compile group: 'org.jboss.weld.se', name: 'weld-se-core', version: '3.0.4.Final'

public class CDI2Fire {

    public static void main(String[] args)  {

        SeContainerInitializer initializer = 
                    SeContainerInitializer.newInstance();

            try (SeContainer container = initializer.disableDiscovery().addPackages(CDI2Fire.class).initialize()) {
                container.select(UsePoolManager.class);
            }
        }
    }

@ApplicationScoped
public class UsePoolManager {

    @Inject 
    private PoolManager poolManager;

    public void init(@Observes @Priority(Interceptor.Priority.APPLICATION - 100)
        @Initialized(ApplicationScoped.class) Object init) throws Exception{
        usePooledObject();
    }

    public void usePooledObject() {
        Object object = this.poolManager.borrowObject();
        System.out.println(object);
    }

}

@Singleton
@Startup
public class PoolManager {

    private Queue<Object> pooledObjects;

    @PostConstruct
    private void init() {
        System.out.println("Hi");
        pooledObjects = new LinkedBlockingQueue<Object>(1_000);
        for (int i = 0; i <= 1000; i++) {
            pooledObjects.offer(i);
        }   
    }


    public void returnObject(Object o) {
        pooledObjects.offer(o);
    }

    public Object borrowObject() {
        return pooledObjects.poll();
    }
}

【讨论】:

  • 这里有一个重要注意事项 - 您正在 SE 中启动 CDI 容器,这完全没问题,但要小心!它只是 CDI 并且您正在使用 EJB 注释(Singleton 和 Startup) - 这些不会起作用,因为我怀疑您是否启动了任何 EJB lite 容器(并且已完成与 CDI SE 的集成,这是 EE 服务器所做的部分)。您需要用一些 CDI 替代品替换它。
  • 感谢西利亚鲁斯。我会仔细检查 CDI 2 上下文中的 EJB 注释使用情况。我会做一些阅读:docs.jboss.org/weld/reference/3.0.4.Final/en-US/pdf/… -
  • 否则,除了焊接依赖项之外,使用以下依赖项现在似乎适用于 Singleton 和 Startup 注释.. : // mvnrepository.com/artifact/javax.inject/javax.inject compile group: 'javax.inject', name: 'javax.inject', version: '1' // mvnrepository.com/artifact/javax.ejb/javax.ejb-api 编译组: 'javax.ejb', name: 'javax.ejb-api', version: '3.2.2'
  • 这不仅仅是关于 CDI 2.0...SE 环境中的 CDI 允许您引导 CDI 容器并在其中工作。但是,它对通常在 EE 容器中引导的 EJB 容器没有任何作用。 EJB != CDI 即使注释经常组合使用。虽然您提到的依赖项将允许您编译代码,但实际的 bean 将不存在 或 将是 @Dependent(例如,就好像您从 CDI 的角度没有在它们上放置注释一样)-行为将根据您使用的 bean 发现模式而有所不同。希望这是有道理的。
【解决方案3】:

关于您自己的答案:您通过将业务方法调用 usePooledObject() 移动到初始化侦听器中来更改完整的应用程序逻辑,而不是像原始示例中那样手动调用它。

这可能不是最好的主意,因为在任意初始化事件上疯狂运行的对象很难控制。

因此:您可能错过的一点是,在select() 之后使用get():

try (SeContainer ...) {
    // replaces the original "new":
    UsePoolManager user = CDI.current().select(UsePoolManager.class).get();
    user.usePooledObject();
}

进一步注意,CDI.current() 的使用消除了在范围内具有具体容器引用的必要性。因此,只要容器处于活动状态,您就可以在应用程序的任何地方使用它。

【讨论】:

  • 我会反对CDI.current(),因为当在具有复杂类加载的环境(例如 EE)中使用时,它可能会导致非常意外的行为。这些部分有许多未定义的部分和实现困难。容器引用是有原因的!
猜你喜欢
  • 2014-11-23
  • 2012-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多