未注入内部依赖项(Weld + JavaSE)
Inner dependency is not being injected (Weld + JavaSE)
我正在通过添加 CDI 来重构旧模块。
我以
结尾
public interface ApiFactory {
...
}
public class ApiFactorySp
implements ApiFactory {
@Inject
UrlProducer urlProducer; // <-- Does not get injected
...
}
和
public interface UrlProducer {
public String getUrl();
}
@Alternative
public class UrlProducerTest
implements UrlProducer {
@Override
public String getUrl() {
return "https://myTestEnv.mydomain/myWebApp";
}
}
为了测试,我在 META-INF
中创建了一个 beans.xml
文件:
<beans
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
bean-discovery-mode="all">
<alternatives>
<class>myOrg.myProject.myPackage.UrlProducerTest</class>
</alternatives>
</beans>
为了测试它,我正在做如图所示 in this blog
public class WeldContext {
public static final WeldContext INSTANCE = new WeldContext();
private final Weld weld;
private final WeldContainer container;
private WeldContext() {
this.weld = new Weld();
this.container = weld.initialize();
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
weld.shutdown();
}
});
}
public <T> T getBean(Class<T> type) {
return container.instance().select(type).get();
}
}
和
public class WeldJUnit4Runner extends BlockJUnit4ClassRunner {
public WeldJUnit4Runner(Class<Object> clazz) throws InitializationError {
super(clazz);
}
@Override
protected Object createTest() {
final Class<?> test = getTestClass().getJavaClass();
return WeldContext.INSTANCE.getBean(test);
}
}
现在,当我尝试测试逻辑时,我会
@RunWith(WeldJUnit4Runner.class)
public class MyTest {
@Inject
UrlProducer urlProducer;
@Inject
ApiFactory apiFactory;
@Test
public void test() {
apiFactory.doSomethingThatRequiresUrlProducer();
}
}
当我 运行 这样做时,两个测试属性都被注入,但我得到 NPE,因为 apiFactory
实例内部的 urlProducer
属性没有被赋值。
为什么 Weld 无法识别 ApiFactory
中的 @Inject
属性?
JDK7、焊接 2.2.10、Junit 4.12
更新:发布问题后,开始尝试一个更简单的全新项目(只有两个界面和三个 类)。使用 Weld "standalone" 没有解决问题,使用 CDI-Unit 确实解决了问题。
然后我修改了我原来的项目以使用CDI-Unit,但它并没有改善任何东西。之后,我将 ApiFactory
中 UrlProducerTest
的注入从字段更改为构造函数(即定义 @Inject ApiFactory(UrlProducer urlProducer)
构造函数)解决了它。我仍然没有尝试使用 "standalone" Weld(明天)的解决方案,但我仍然想知道为什么场注入不起作用。
因为 ApiFactorySp
不是 CDI bean。您需要使用 @Named
注释 class 以将 class 标识为 CDI 执行依赖注入的 CDI bean。
如果 UrlProducerTest
是替代方案,并且您想注入此 bean,则应将此 class 添加到 beans.xml
到 <alternatives>
标记中。
编辑:
我相信如果某些 bean 无法注入,您会收到 'unsatisfied/ambiguous dependencies' 消息的异常。 Null
如果您使用返回 null 的 CDI producer
方法,则可能会被注入,但这不是您的情况。
所以如果控制台没有错误,我有两个假设:
注入根本不起作用,你会得到 NPE 因为 apiFactory
是 null
您在注入前使用urlProducer
。例如,来自构造函数或初始化块(未提供 apiFactory.doSomethingThatRequiresUrlProducer()
)。因此,将此逻辑移至某个方法并通过 @PostConstruct
对其进行注释
我正在通过添加 CDI 来重构旧模块。
我以
结尾public interface ApiFactory {
...
}
public class ApiFactorySp
implements ApiFactory {
@Inject
UrlProducer urlProducer; // <-- Does not get injected
...
}
和
public interface UrlProducer {
public String getUrl();
}
@Alternative
public class UrlProducerTest
implements UrlProducer {
@Override
public String getUrl() {
return "https://myTestEnv.mydomain/myWebApp";
}
}
为了测试,我在 META-INF
中创建了一个 beans.xml
文件:
<beans
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
bean-discovery-mode="all">
<alternatives>
<class>myOrg.myProject.myPackage.UrlProducerTest</class>
</alternatives>
</beans>
为了测试它,我正在做如图所示 in this blog
public class WeldContext {
public static final WeldContext INSTANCE = new WeldContext();
private final Weld weld;
private final WeldContainer container;
private WeldContext() {
this.weld = new Weld();
this.container = weld.initialize();
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
weld.shutdown();
}
});
}
public <T> T getBean(Class<T> type) {
return container.instance().select(type).get();
}
}
和
public class WeldJUnit4Runner extends BlockJUnit4ClassRunner {
public WeldJUnit4Runner(Class<Object> clazz) throws InitializationError {
super(clazz);
}
@Override
protected Object createTest() {
final Class<?> test = getTestClass().getJavaClass();
return WeldContext.INSTANCE.getBean(test);
}
}
现在,当我尝试测试逻辑时,我会
@RunWith(WeldJUnit4Runner.class)
public class MyTest {
@Inject
UrlProducer urlProducer;
@Inject
ApiFactory apiFactory;
@Test
public void test() {
apiFactory.doSomethingThatRequiresUrlProducer();
}
}
当我 运行 这样做时,两个测试属性都被注入,但我得到 NPE,因为 apiFactory
实例内部的 urlProducer
属性没有被赋值。
为什么 Weld 无法识别 ApiFactory
中的 @Inject
属性?
JDK7、焊接 2.2.10、Junit 4.12
更新:发布问题后,开始尝试一个更简单的全新项目(只有两个界面和三个 类)。使用 Weld "standalone" 没有解决问题,使用 CDI-Unit 确实解决了问题。
然后我修改了我原来的项目以使用CDI-Unit,但它并没有改善任何东西。之后,我将 ApiFactory
中 UrlProducerTest
的注入从字段更改为构造函数(即定义 @Inject ApiFactory(UrlProducer urlProducer)
构造函数)解决了它。我仍然没有尝试使用 "standalone" Weld(明天)的解决方案,但我仍然想知道为什么场注入不起作用。
因为 ApiFactorySp
不是 CDI bean。您需要使用 @Named
注释 class 以将 class 标识为 CDI 执行依赖注入的 CDI bean。
如果 UrlProducerTest
是替代方案,并且您想注入此 bean,则应将此 class 添加到 beans.xml
到 <alternatives>
标记中。
编辑:
我相信如果某些 bean 无法注入,您会收到 'unsatisfied/ambiguous dependencies' 消息的异常。 Null
如果您使用返回 null 的 CDI producer
方法,则可能会被注入,但这不是您的情况。
所以如果控制台没有错误,我有两个假设:
注入根本不起作用,你会得到 NPE 因为
apiFactory
是 null您在注入前使用
urlProducer
。例如,来自构造函数或初始化块(未提供apiFactory.doSomethingThatRequiresUrlProducer()
)。因此,将此逻辑移至某个方法并通过 @PostConstruct 对其进行注释