java EE 8 中的依赖注入 (CDI)

dependency injection (CDI) in java EE 8

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

PoolManager Class:

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 Class:

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();
    }
}

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

如有任何帮助,我们将不胜感激。

谢谢!


正在检查我使用的是 SE 还是 EE 以进行说明...

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

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

在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();
    }
}

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

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

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

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

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