在JBoss AS7上运行,我有:
import javax.inject.Singleton;
@Singleton
public class Connections {
private final List<AtmosphereResource> connections = new ArrayList<AtmosphereResource>();
public void add(AtmosphereResource event) {
connections.add(event);
}
}
和此:
import javax.inject.Inject;
public class PubSubAtmosphereHandler extends AbstractReflectorAtmosphereHandler {
@Inject
private Connections connections;
@Override
public void onRequest(AtmosphereResource event) throws IOException {
[...]
connections.add(event); // <---
}
指定行上的NPE。在阅读了无数页面和示例之后,这是重复几十次的方法之一,但它不起作用。我有空的beans.xml,放在我的WEB-INF中。我在这里缺少什么?
答案 0 :(得分:2)
经过一番研究,结果发现Atmosphere为这种功能提供了(目前已经破解)钩子。这意味着 IS 可以简单地使用您的普通注释,并使其与Atmosphere一起使用,尽管有“外国”实例化。
如果您知道代码的部署位置,您可以通过在同一个包中具有相同名称的类并使其提供正确的Injector来简单地覆盖Atmosphere中的默认noop InjectorProvider类。
我在本回答的最后添加了JBoss AS7的代码,以及应该在Google Guice和Spring上运行的代码的链接,我还没有测试过。
如果您需要在多个平台上运行代码,则可能需要弄清楚如何检测正在运行的内容,然后返回相应的Injector。由于我对Guice和Spring不是很熟悉,所以我会把这个练习留给读者。
JBoss AS7的脏'初稿'代码(请记住,这必须进入声明的包以覆盖默认的noop提供程序):
package org.atmosphere.di;
import java.util.NoSuchElementException;
import java.util.ServiceLoader;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.InjectionTarget;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class InjectorProvider {
private InjectorProvider() {}
public static Injector getInjector() {
return LazyProvider.INJECTOR;
}
private static final class LazyProvider {
private static final Injector INJECTOR;
static {
Injector injector = new Injector() {
@Override public void inject(final Object o) {
try {
final BeanManager bm = (BeanManager) new InitialContext().lookup("java:comp/BeanManager");
final CreationalContext cc = bm.createCreationalContext(null);
final InjectionTarget it = bm.createInjectionTarget(bm.createAnnotatedType(o.getClass()));
it.inject(o, cc);
cc.release();
} catch (final NamingException e) {
e.printStackTrace();
}
}
};
try {
injector = ServiceLoader.load(Injector.class).iterator().next();
} catch (final NoSuchElementException e) {}
INJECTOR = injector;
}
}
}
请注意,包装代码取自Atmosphere代码库,是一种在Java中使用Singletons的非常糟糕的方法。您可能不希望在生产中使用“原样”。
答案 1 :(得分:1)
其他人试图说的是PubSubAtmosphereHandler的生命周期必须由容器(又名JBoss)控制。
换句话说,容器负责创建和初始化PubSubAtmosphereHandler的实例。
如果您或您的框架创建此对象,则不会进行注射。
答案 2 :(得分:0)
有可能使用jndi获取BeanManager。然后你可以从那里拿到豆子。
BeanManager bm = initialContext.lookup("java:comp/BeanManager");
Bean<Connections> bean = (Bean<Connections>) bm.getBeans(Connections.class).iterator().next();
CreationalContext<Connections> ctx = bm.createCreationalContext(bean);
Connections connections = (Connections) bm.getReference(bean, Connections.class, ctx);
connections.add(event);